blob: 94ad045ef71bacdfa19e0db3a731cad2c5e28f45 [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 Freyther5816bcf2014-04-04 11:43:09 +020024#if defined(__FreeBSD__)
25#include <sys/endian.h>
26#endif
27
jjako0fe0df02004-09-17 11:30:40 +000028#include "../config.h"
29#ifdef HAVE_STDINT_H
30#include <stdint.h>
31#endif
jjako52c24142002-12-16 13:33:51 +000032
33#include <syslog.h>
34#include <stdio.h>
35#include <stdarg.h>
36#include <stdlib.h>
37#include <sys/time.h>
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <sys/stat.h>
43#include <time.h>
44#include <unistd.h>
45#include <string.h>
46#include <errno.h>
47#include <fcntl.h>
48
49#include <arpa/inet.h>
50
jjakobae2cd42004-01-09 12:04:39 +000051/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000052
53#include "pdp.h"
54#include "gtp.h"
55#include "gtpie.h"
56#include "queue.h"
57
Harald Welte95848ba2011-11-02 18:17:50 +010058/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
59#define N3_REQUESTS 5
60
61#define T3_REQUEST 3
62
jjako1db1c812003-07-06 20:53:57 +000063/* Error reporting functions */
64
Harald Weltebed35df2011-11-02 13:06:18 +010065void gtp_err(int priority, char *filename, int linenum, char *fmt, ...)
66{
67 va_list args;
68 char buf[ERRMSG_SIZE];
jjako1db1c812003-07-06 20:53:57 +000069
Harald Weltebed35df2011-11-02 13:06:18 +010070 va_start(args, fmt);
71 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
72 va_end(args);
73 buf[ERRMSG_SIZE - 1] = 0;
74 syslog(priority, "%s: %d: %s", filename, linenum, buf);
jjako1db1c812003-07-06 20:53:57 +000075}
76
77void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +010078 void *pack, unsigned len, char *fmt, ...)
79{
jjako1db1c812003-07-06 20:53:57 +000080
Harald Weltebed35df2011-11-02 13:06:18 +010081 va_list args;
82 char buf[ERRMSG_SIZE];
83 char buf2[ERRMSG_SIZE];
84 unsigned int n;
85 int pos;
86
87 va_start(args, fmt);
88 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
89 va_end(args);
90 buf[ERRMSG_SIZE - 1] = 0;
91
92 snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
93 inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
94 buf2[ERRMSG_SIZE - 1] = 0;
95 pos = strlen(buf2);
96 for (n = 0; n < len; n++) {
97 if ((pos + 4) < ERRMSG_SIZE) {
98 sprintf((buf2 + pos), " %02hhx",
99 ((unsigned char *)pack)[n]);
100 pos += 3;
101 }
102 }
103 buf2[pos] = 0;
104
105 syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
jjako1db1c812003-07-06 20:53:57 +0000106
107}
108
jjako52c24142002-12-16 13:33:51 +0000109/* API Functions */
110
Harald Weltebed35df2011-11-02 13:06:18 +0100111const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +0000112{
Harald Weltebed35df2011-11-02 13:06:18 +0100113 return VERSION;
jjako52c24142002-12-16 13:33:51 +0000114}
115
116/* gtp_new */
117/* gtp_free */
118
Harald Weltebed35df2011-11-02 13:06:18 +0100119int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
120 uint64_t imsi, uint8_t nsapi)
121{
122 return pdp_newpdp(pdp, imsi, nsapi, NULL);
jjako52c24142002-12-16 13:33:51 +0000123}
124
Harald Weltebed35df2011-11-02 13:06:18 +0100125int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
126{
127 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000128}
129
jjako52c24142002-12-16 13:33:51 +0000130/* gtp_gpdu */
131
Harald Weltebed35df2011-11-02 13:06:18 +0100132extern int gtp_fd(struct gsn_t *gsn)
133{
134 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000135}
136
137/* gtp_decaps */
138/* gtp_retrans */
139/* gtp_retranstimeout */
140
jjako08d331d2003-10-13 20:33:30 +0000141int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100142 int (*cb) (struct sockaddr_in * peer))
143{
144 gsn->cb_unsup_ind = cb;
145 return 0;
jjako08d331d2003-10-13 20:33:30 +0000146}
147
jjako2c381332003-10-21 19:09:53 +0000148int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100149 int (*cb) (struct sockaddr_in * peer))
150{
151 gsn->cb_extheader_ind = cb;
152 return 0;
jjako2c381332003-10-21 19:09:53 +0000153}
154
jjako08d331d2003-10-13 20:33:30 +0000155/* API: Initialise delete context callback */
156/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100157int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000158{
Harald Weltebed35df2011-11-02 13:06:18 +0100159 gsn->cb_delete_context = cb;
160 return 0;
jjako52c24142002-12-16 13:33:51 +0000161}
162
jjako52c24142002-12-16 13:33:51 +0000163int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100164 int (*cb) (int type, int cause,
165 struct pdp_t * pdp, void *cbp))
166{
167 gsn->cb_conf = cb;
168 return 0;
jjako52c24142002-12-16 13:33:51 +0000169}
170
Harald Welte629e9862010-12-24 20:58:09 +0100171int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100172 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
173{
174 gsn->cb_recovery = cb;
175 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100176}
177
jjako08d331d2003-10-13 20:33:30 +0000178extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100179 int (*cb_data_ind) (struct pdp_t * pdp,
180 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000181{
Harald Weltebed35df2011-11-02 13:06:18 +0100182 gsn->cb_data_ind = cb_data_ind;
183 return 0;
jjako52c24142002-12-16 13:33:51 +0000184}
185
jjako08d331d2003-10-13 20:33:30 +0000186/**
187 * get_default_gtp()
188 * Generate a GPRS Tunneling Protocol signalling packet header, depending
189 * on GTP version and message type. pdp is used for teid/flow label.
190 * *packet must be allocated by the calling function, and be large enough
191 * to hold the packet header.
192 * returns the length of the header. 0 on error.
193 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100194static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
195{
196 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
197 struct gtp1_header_long *gtp1_default =
198 (struct gtp1_header_long *)packet;
199 switch (version) {
200 case 0:
201 /* Initialise "standard" GTP0 header */
202 memset(gtp0_default, 0, sizeof(struct gtp0_header));
203 gtp0_default->flags = 0x1e;
204 gtp0_default->type = hton8(type);
205 gtp0_default->spare1 = 0xff;
206 gtp0_default->spare2 = 0xff;
207 gtp0_default->spare3 = 0xff;
208 gtp0_default->number = 0xff;
209 return GTP0_HEADER_SIZE;
210 case 1:
211 /* Initialise "standard" GTP1 header */
212 /* 29.060: 8.2: S=1 and PN=0 */
213 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
214 /* and Supported Extension Headers Notification, the S field shall be */
215 /* set to 1 */
216 /* Currently extension headers are not supported */
217 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
218 gtp1_default->flags = 0x32; /* No extension, enable sequence, no N-PDU */
219 gtp1_default->type = hton8(type);
220 return GTP1_HEADER_SIZE_LONG;
221 default:
222 gtp_err(LOG_ERR, __FILE__, __LINE__,
223 "Unknown GTP packet version");
224 return 0;
225 }
jjako52c24142002-12-16 13:33:51 +0000226}
227
jjako08d331d2003-10-13 20:33:30 +0000228/**
229 * get_seq()
230 * Get sequence number of a packet.
231 * Returns 0 on error
232 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100233static uint16_t get_seq(void *pack)
234{
235 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000236
Harald Weltebed35df2011-11-02 13:06:18 +0100237 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
238 return ntoh16(packet->gtp0.h.seq);
239 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
240 return ntoh16(packet->gtp1l.h.seq);
241 } else {
242 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
243 return 0;
244 }
jjako08d331d2003-10-13 20:33:30 +0000245}
246
247/**
248 * get_tid()
249 * Get tunnel identifier of a packet.
250 * Returns 0 on error
251 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100252static uint64_t get_tid(void *pack)
253{
254 union gtp_packet *packet = (union gtp_packet *)pack;
255
256 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100257 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100258 }
259 return 0;
jjako08d331d2003-10-13 20:33:30 +0000260}
261
262/**
263 * get_hlen()
264 * Get the header length of a packet.
265 * Returns 0 on error
266 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100267static uint16_t get_hlen(void *pack)
268{
269 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000270
Harald Weltebed35df2011-11-02 13:06:18 +0100271 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
272 return GTP0_HEADER_SIZE;
273 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
274 return GTP1_HEADER_SIZE_LONG;
275 } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
276 return GTP1_HEADER_SIZE_SHORT;
277 } else {
278 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
279 return 0;
280 }
jjako08d331d2003-10-13 20:33:30 +0000281}
282
283/**
284 * get_tei()
285 * Get the tunnel endpoint identifier (flow label) of a packet.
286 * Returns 0xffffffff on error.
287 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100288static uint32_t get_tei(void *pack)
289{
290 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000291
Harald Weltebed35df2011-11-02 13:06:18 +0100292 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
293 return ntoh16(packet->gtp0.h.flow);
294 } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
295 return ntoh32(packet->gtp1l.h.tei);
296 } else {
297 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
298 return 0xffffffff;
299 }
jjako08d331d2003-10-13 20:33:30 +0000300}
jjakoa7cd2492003-04-11 09:40:12 +0000301
jjako52c24142002-12-16 13:33:51 +0000302int print_packet(void *packet, unsigned len)
303{
Harald Weltebed35df2011-11-02 13:06:18 +0100304 unsigned int i;
305 printf("The packet looks like this (%d bytes):\n", len);
306 for (i = 0; i < len; i++) {
307 printf("%02x ", (unsigned char)*(char *)(packet + i));
308 if (!((i + 1) % 16))
309 printf("\n");
310 };
311 printf("\n");
312 return 0;
jjako52c24142002-12-16 13:33:51 +0000313}
314
Harald Weltebed35df2011-11-02 13:06:18 +0100315char *snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
316 void *pack, unsigned len, char *buf, int size)
317{
318 unsigned int n;
319 int pos;
320 snprintf(buf, size, "Packet from %s:%u, length: %d, content:",
321 inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
322 buf[size - 1] = 0;
323 pos = strlen(buf);
324 for (n = 0; n < len; n++) {
325 if ((pos + 4) < size) {
326 sprintf((buf + pos), " %02hhx",
327 ((unsigned char *)pack)[n]);
328 pos += 3;
329 }
330 }
331 buf[pos] = 0;
332 return buf;
jjako52c24142002-12-16 13:33:51 +0000333}
334
jjako52c24142002-12-16 13:33:51 +0000335/* ***********************************************************
336 * Reliable delivery of signalling messages
337 *
338 * Sequence numbers are used for both signalling messages and
339 * data messages.
340 *
341 * For data messages each tunnel maintains a sequence counter,
342 * which is incremented by one each time a new data message
343 * is sent. The sequence number starts at (0) zero at tunnel
344 * establishment, and wraps around at 65535 (29.060 9.3.1.1
345 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
346 * or can be used to check the validity of the message in the
347 * receiver, or for reordering af packets.
348 *
349 * For signalling messages the sequence number is used by
350 * signalling messages for which a response is defined. A response
351 * message should copy the sequence from the corresponding request
352 * message. The sequence number "unambiguously" identifies a request
353 * message within a given path, with a path being defined as a set of
354 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
355 * messages shall be responded to, and all response messages associated
356 * with a certain request shall always include the same information"
357 *
358 * We take this to mean that the GSN transmitting a request is free to
359 * choose the sequence number, as long as it is unique within a given path.
360 * It means that we are allowed to count backwards, or roll over at 17
361 * if we prefer that. It also means that we can use the same counter for
362 * all paths. This has the advantage that the transmitted request sequence
363 * numbers are unique within each GSN, and also we dont have to mess around
364 * with path setup and teardown.
365 *
366 * If a response message is lost, the request will be retransmitted, and
367 * the receiving GSN will receive a "duplicated" request. The standard
368 * requires the receiving GSN to send a response, with the same information
369 * as in the original response. For most messages this happens automatically:
370 *
371 * Echo: Automatically dublicates the original response
372 * Create pdp context: The SGSN may send create context request even if
373 * a context allready exist (imsi+nsapi?). This means that the reply will
374 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000375 * side effects in the application which is asked twice to validate
376 * the login.
jjako52c24142002-12-16 13:33:51 +0000377 * Update pdp context: Automatically dublicates the original response???
378 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
379 * a nonexist reply message.
380 *
381 * The correct solution will be to make a queue containing response messages.
382 * This queue should be checked whenever a request is received. If the
383 * response is allready in the queue that response should be transmitted.
384 * It should be possible to find messages in this queue on the basis of
385 * the sequence number and peer GSN IP address (The sequense number is unique
386 * within each path). This need to be implemented by a hash table. Furthermore
387 * it should be possibly to delete messages based on a timeout. This can be
388 * achieved by means of a linked list. The timeout value need to be larger
389 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
390 * set in the peer GSN, so there is no way to know these parameters. On the
391 * other hand the timeout value need to be so small that we do not receive
392 * wraparound sequence numbere before the message is deleted. 60 seconds is
393 * probably not a bad choise.
394 *
395 * This queue however is first really needed from gtp1.
396 *
397 * gtp_req:
398 * Send off a signalling message with appropiate sequence
399 * number. Store packet in queue.
400 * gtp_conf:
401 * Remove an incoming confirmation from the queue
402 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000403 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000404 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000405 * gtp_notification:
406 * Send off a notification message. This is neither a request nor
407 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000408 * gtp_retrans:
409 * Retransmit any outstanding packets which have exceeded
410 * a predefined timeout.
411 *************************************************************/
412
jjako08d331d2003-10-13 20:33:30 +0000413int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100414 union gtp_packet *packet, int len,
415 struct in_addr *inetaddr, void *cbp)
416{
417 struct sockaddr_in addr;
418 struct qmsg_t *qmsg;
419 int fd;
jjako08d331d2003-10-13 20:33:30 +0000420
Harald Weltebed35df2011-11-02 13:06:18 +0100421 memset(&addr, 0, sizeof(addr));
422 addr.sin_family = AF_INET;
423 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000424#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100425 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000426#endif
jjako52c24142002-12-16 13:33:51 +0000427
Harald Weltebed35df2011-11-02 13:06:18 +0100428 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
429 addr.sin_port = htons(GTP0_PORT);
430 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
431 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100432 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100433 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100434 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100435 }
Harald Weltebed35df2011-11-02 13:06:18 +0100436 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
437 || (packet->gtp0.h.type == GTP_ERROR)))
438 packet->gtp0.h.flow = hton16(pdp->flru);
439 else if (pdp)
440 packet->gtp0.h.flow = hton16(pdp->flrc);
441 fd = gsn->fd0;
442 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
443 addr.sin_port = htons(GTP1C_PORT);
444 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
445 packet->gtp1l.h.seq = hton16(gsn->seq_next);
446 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
447 (packet->gtp1l.h.type == GTP_ERROR)))
448 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
449 else if (pdp)
450 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
451 fd = gsn->fd1c;
452 } else {
453 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
454 return -1;
455 }
jjako52c24142002-12-16 13:33:51 +0000456
Harald Weltebed35df2011-11-02 13:06:18 +0100457 if (sendto(fd, packet, len, 0,
458 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
459 gsn->err_sendto++;
460 gtp_err(LOG_ERR, __FILE__, __LINE__,
461 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
462 (unsigned long)&packet, len, strerror(errno));
463 return -1;
464 }
465
466 /* Use new queue structure */
467 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
468 gsn->err_queuefull++;
469 gtp_err(LOG_ERR, __FILE__, __LINE__,
470 "Retransmit queue is full");
471 } else {
472 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
473 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100474 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100475 qmsg->retrans = 0; /* No retransmissions so far */
476 qmsg->cbp = cbp;
477 qmsg->type = ntoh8(packet->gtp0.h.type);
478 qmsg->fd = fd;
479 }
480 gsn->seq_next++; /* Count up this time */
481 return 0;
jjako52c24142002-12-16 13:33:51 +0000482}
483
484/* gtp_conf
485 * Remove signalling packet from retransmission queue.
486 * return 0 on success, EOF if packet was not found */
487
488int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100489 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
490{
jjako52c24142002-12-16 13:33:51 +0000491
Harald Weltebed35df2011-11-02 13:06:18 +0100492 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000493
Harald Weltebed35df2011-11-02 13:06:18 +0100494 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
495 seq = ntoh16(packet->gtp0.h.seq);
496 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
497 seq = ntoh16(packet->gtp1l.h.seq);
498 else {
499 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
500 "Unknown GTP packet version");
501 return EOF;
502 }
jjako08d331d2003-10-13 20:33:30 +0000503
Harald Weltebed35df2011-11-02 13:06:18 +0100504 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
505 gsn->err_seq++;
506 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
507 "Confirmation packet not found in queue");
508 return EOF;
509 }
jjako52c24142002-12-16 13:33:51 +0000510
Harald Weltebed35df2011-11-02 13:06:18 +0100511 return 0;
jjako52c24142002-12-16 13:33:51 +0000512}
513
Harald Weltebed35df2011-11-02 13:06:18 +0100514int gtp_retrans(struct gsn_t *gsn)
515{
516 /* Retransmit any outstanding packets */
517 /* Remove from queue if maxretrans exceeded */
518 time_t now;
519 struct qmsg_t *qmsg;
520 now = time(NULL);
521 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000522
Harald Welte95848ba2011-11-02 18:17:50 +0100523 /* get first element in queue, as long as the timeout of that
524 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100525 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
526 (qmsg->timeout <= now)) {
527 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100528 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100529 if (gsn->cb_conf)
530 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
531 queue_freemsg(gsn->queue_req, qmsg);
532 } else {
533 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
534 (struct sockaddr *)&qmsg->peer,
535 sizeof(struct sockaddr_in)) < 0) {
536 gsn->err_sendto++;
537 gtp_err(LOG_ERR, __FILE__, __LINE__,
538 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s",
539 gsn->fd0, (unsigned long)&qmsg->p,
540 qmsg->l, strerror(errno));
541 }
542 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100543 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100544 qmsg->retrans++;
545 }
546 }
jjako52c24142002-12-16 13:33:51 +0000547
Harald Weltebed35df2011-11-02 13:06:18 +0100548 /* Also clean up reply timeouts */
549 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
550 (qmsg->timeout < now)) {
551 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
552 queue_freemsg(gsn->queue_resp, qmsg);
553 }
jjako52c24142002-12-16 13:33:51 +0000554
Harald Weltebed35df2011-11-02 13:06:18 +0100555 return 0;
jjako52c24142002-12-16 13:33:51 +0000556}
557
Harald Weltebed35df2011-11-02 13:06:18 +0100558int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
559{
560 time_t now, later;
561 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000562
Harald Weltebed35df2011-11-02 13:06:18 +0100563 if (queue_getfirst(gsn->queue_req, &qmsg)) {
564 timeout->tv_sec = 10;
565 timeout->tv_usec = 0;
566 } else {
567 now = time(NULL);
568 later = qmsg->timeout;
569 timeout->tv_sec = later - now;
570 timeout->tv_usec = 0;
571 if (timeout->tv_sec < 0)
572 timeout->tv_sec = 0; /* No negative allowed */
573 if (timeout->tv_sec > 10)
574 timeout->tv_sec = 10; /* Max sleep for 10 sec */
575 }
576 return 0;
jjako52c24142002-12-16 13:33:51 +0000577}
578
Harald Weltebed35df2011-11-02 13:06:18 +0100579int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000580 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100581 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
582{
583 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000584
Harald Weltebed35df2011-11-02 13:06:18 +0100585 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
586 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
587 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100588 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100589 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
590 (packet->gtp0.h.type == GTP_ERROR)))
591 packet->gtp0.h.flow = hton16(pdp->flru);
592 else if (pdp)
593 packet->gtp0.h.flow = hton16(pdp->flrc);
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 if (pdp && (fd == gsn->fd1u))
598 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
599 else if (pdp)
600 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
601 } else {
602 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
603 return -1;
604 }
jjako08d331d2003-10-13 20:33:30 +0000605
Harald Weltebed35df2011-11-02 13:06:18 +0100606 if (fcntl(fd, F_SETFL, 0)) {
607 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
608 return -1;
609 }
jjako52c24142002-12-16 13:33:51 +0000610
Harald Weltebed35df2011-11-02 13:06:18 +0100611 if (sendto(fd, packet, len, 0,
612 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
613 gsn->err_sendto++;
614 gtp_err(LOG_ERR, __FILE__, __LINE__,
615 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
616 (unsigned long)&packet, len, strerror(errno));
617 return -1;
618 }
619
620 /* Use new queue structure */
621 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
622 gsn->err_queuefull++;
623 gtp_err(LOG_ERR, __FILE__, __LINE__,
624 "Retransmit queue is full");
625 } else {
626 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
627 qmsg->l = len;
628 qmsg->timeout = time(NULL) + 60; /* When to timeout */
629 qmsg->retrans = 0; /* No retransmissions so far */
630 qmsg->cbp = NULL;
631 qmsg->type = 0;
632 qmsg->fd = fd;
633 }
634 return 0;
jjako52c24142002-12-16 13:33:51 +0000635}
636
jjako2c381332003-10-21 19:09:53 +0000637int gtp_notification(struct gsn_t *gsn, int version,
638 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100639 struct sockaddr_in *peer, int fd, uint16_t seq)
640{
jjako2c381332003-10-21 19:09:53 +0000641
Harald Weltebed35df2011-11-02 13:06:18 +0100642 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000643
Harald Weltebed35df2011-11-02 13:06:18 +0100644 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000645
Harald Weltebed35df2011-11-02 13:06:18 +0100646 /* In GTP0 notifications are treated as replies. In GTP1 they
647 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000648
Harald Weltebed35df2011-11-02 13:06:18 +0100649 if (fd == gsn->fd1c)
650 addr.sin_port = htons(GTP1C_PORT);
651 else if (fd == gsn->fd1u)
652 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000653
Harald Weltebed35df2011-11-02 13:06:18 +0100654 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
655 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
656 packet->gtp0.h.seq = hton16(seq);
657 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
658 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
659 packet->gtp1l.h.seq = hton16(seq);
660 } else {
661 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
662 return -1;
663 }
664
665 if (fcntl(fd, F_SETFL, 0)) {
666 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
667 return -1;
668 }
669
670 if (sendto(fd, packet, len, 0,
671 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
672 gsn->err_sendto++;
673 gtp_err(LOG_ERR, __FILE__, __LINE__,
674 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
675 (unsigned long)&packet, len, strerror(errno));
676 return -1;
677 }
678 return 0;
jjako2c381332003-10-21 19:09:53 +0000679}
680
Harald Weltebed35df2011-11-02 13:06:18 +0100681int gtp_dublicate(struct gsn_t *gsn, int version,
682 struct sockaddr_in *peer, uint16_t seq)
683{
684 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000685
Harald Weltebed35df2011-11-02 13:06:18 +0100686 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
687 return EOF; /* Notfound */
688 }
jjakoa7cd2492003-04-11 09:40:12 +0000689
Harald Weltebed35df2011-11-02 13:06:18 +0100690 if (fcntl(qmsg->fd, F_SETFL, 0)) {
691 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
692 return -1;
693 }
694
695 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
696 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
697 gsn->err_sendto++;
698 gtp_err(LOG_ERR, __FILE__, __LINE__,
699 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s",
700 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
701 strerror(errno));
702 }
703 return 0;
jjako52c24142002-12-16 13:33:51 +0000704}
705
jjako52c24142002-12-16 13:33:51 +0000706/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100707static void log_restart(struct gsn_t *gsn)
708{
jjako52c24142002-12-16 13:33:51 +0000709 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200710 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000711 int counter = 0;
712 char filename[NAMESIZE];
713
Harald Weltebed35df2011-11-02 13:06:18 +0100714 filename[NAMESIZE - 1] = 0; /* No null term. guarantee by strncpy */
715 strncpy(filename, gsn->statedir, NAMESIZE - 1);
716 strncat(filename, RESTART_FILE, NAMESIZE - 1 - sizeof(RESTART_FILE));
jjako52c24142002-12-16 13:33:51 +0000717
718 i = umask(022);
719
720 /* We try to open file. On failure we will later try to create file */
721 if (!(f = fopen(filename, "r"))) {
jjako581c9f02003-10-22 11:28:20 +0000722
Harald Weltebed35df2011-11-02 13:06:18 +0100723 gtp_err(LOG_ERR, __FILE__, __LINE__,
724 "State information file (%s) not found. Creating new file.",
725 filename);
726 } else {
727 umask(i);
728 rc = fscanf(f, "%d", &counter);
729 if (rc != 1) {
730 gtp_err(LOG_ERR, __FILE__, __LINE__,
731 "fscanf failed to read counter value");
732 return;
733 }
734 if (fclose(f)) {
735 gtp_err(LOG_ERR, __FILE__, __LINE__,
736 "fclose failed: Error = %s", strerror(errno));
737 }
jjako52c24142002-12-16 13:33:51 +0000738 }
Harald Weltebed35df2011-11-02 13:06:18 +0100739
740 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000741 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100742
jjako52c24142002-12-16 13:33:51 +0000743 if (!(f = fopen(filename, "w"))) {
Harald Weltebed35df2011-11-02 13:06:18 +0100744 gtp_err(LOG_ERR, __FILE__, __LINE__,
745 "fopen(path=%s, mode=%s) failed: Error = %s", filename,
746 "w", strerror(errno));
747 return;
jjako52c24142002-12-16 13:33:51 +0000748 }
749
750 umask(i);
751 fprintf(f, "%d\n", gsn->restart_counter);
752 if (fclose(f)) {
Harald Weltebed35df2011-11-02 13:06:18 +0100753 gtp_err(LOG_ERR, __FILE__, __LINE__,
754 "fclose failed: Error = %s", strerror(errno));
755 return;
jjako52c24142002-12-16 13:33:51 +0000756 }
757}
758
jjako1db1c812003-07-06 20:53:57 +0000759int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100760 int mode)
jjako52c24142002-12-16 13:33:51 +0000761{
Harald Weltebed35df2011-11-02 13:06:18 +0100762 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000763
Harald Weltebed35df2011-11-02 13:06:18 +0100764 syslog(LOG_ERR, "GTP: gtp_newgsn() started");
jjako52c24142002-12-16 13:33:51 +0000765
Harald Weltebed35df2011-11-02 13:06:18 +0100766 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000767
Harald Weltebed35df2011-11-02 13:06:18 +0100768 (*gsn)->statedir = statedir;
769 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000770
Harald Weltebed35df2011-11-02 13:06:18 +0100771 /* Initialise sequence number */
772 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000773
Harald Weltebed35df2011-11-02 13:06:18 +0100774 /* Initialise request retransmit queue */
775 queue_new(&(*gsn)->queue_req);
776 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000777
Harald Weltebed35df2011-11-02 13:06:18 +0100778 /* Initialise pdp table */
779 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000780
Harald Weltebed35df2011-11-02 13:06:18 +0100781 /* Initialise call back functions */
782 (*gsn)->cb_create_context_ind = 0;
783 (*gsn)->cb_delete_context = 0;
784 (*gsn)->cb_unsup_ind = 0;
785 (*gsn)->cb_conf = 0;
786 (*gsn)->cb_data_ind = 0;
787
788 /* Store function parameters */
789 (*gsn)->gsnc = *listen;
790 (*gsn)->gsnu = *listen;
791 (*gsn)->mode = mode;
792
793 /* Create GTP version 0 socket */
794 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
795 (*gsn)->err_socket++;
796 gtp_err(LOG_ERR, __FILE__, __LINE__,
797 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
798 AF_INET, SOCK_DGRAM, 0, strerror(errno));
799 return -1;
800 }
801
802 memset(&addr, 0, sizeof(addr));
803 addr.sin_family = AF_INET;
804 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
805 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000806#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100807 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000808#endif
jjako08d331d2003-10-13 20:33:30 +0000809
Harald Weltebed35df2011-11-02 13:06:18 +0100810 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
811 (*gsn)->err_socket++;
812 gtp_err(LOG_ERR, __FILE__, __LINE__,
813 "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s",
814 (*gsn)->fd0, (unsigned long)&addr, sizeof(addr),
815 strerror(errno));
816 return -1;
817 }
jjako08d331d2003-10-13 20:33:30 +0000818
Harald Weltebed35df2011-11-02 13:06:18 +0100819 /* Create GTP version 1 control plane socket */
820 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
821 (*gsn)->err_socket++;
822 gtp_err(LOG_ERR, __FILE__, __LINE__,
823 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
824 AF_INET, SOCK_DGRAM, 0, strerror(errno));
825 return -1;
826 }
827
828 memset(&addr, 0, sizeof(addr));
829 addr.sin_family = AF_INET;
830 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
831 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000832#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100833 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000834#endif
jjako08d331d2003-10-13 20:33:30 +0000835
Harald Weltebed35df2011-11-02 13:06:18 +0100836 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
837 (*gsn)->err_socket++;
838 gtp_err(LOG_ERR, __FILE__, __LINE__,
839 "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
840 (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
841 strerror(errno));
842 return -1;
843 }
jjako08d331d2003-10-13 20:33:30 +0000844
Harald Weltebed35df2011-11-02 13:06:18 +0100845 /* Create GTP version 1 user plane socket */
846 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
847 (*gsn)->err_socket++;
848 gtp_err(LOG_ERR, __FILE__, __LINE__,
849 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
850 AF_INET, SOCK_DGRAM, 0, strerror(errno));
851 return -1;
852 }
853
854 memset(&addr, 0, sizeof(addr));
855 addr.sin_family = AF_INET;
856 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
857 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000858#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100859 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000860#endif
jjako52c24142002-12-16 13:33:51 +0000861
Harald Weltebed35df2011-11-02 13:06:18 +0100862 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
863 (*gsn)->err_socket++;
864 gtp_err(LOG_ERR, __FILE__, __LINE__,
865 "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
866 (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
867 strerror(errno));
868 return -1;
869 }
870
871 return 0;
jjako52c24142002-12-16 13:33:51 +0000872}
873
Harald Weltebed35df2011-11-02 13:06:18 +0100874int gtp_free(struct gsn_t *gsn)
875{
jjako52c24142002-12-16 13:33:51 +0000876
Harald Weltebed35df2011-11-02 13:06:18 +0100877 /* Clean up retransmit queues */
878 queue_free(gsn->queue_req);
879 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000880
Harald Weltebed35df2011-11-02 13:06:18 +0100881 close(gsn->fd0);
882 close(gsn->fd1c);
883 close(gsn->fd1u);
884
885 free(gsn);
886 return 0;
jjako52c24142002-12-16 13:33:51 +0000887}
888
889/* ***********************************************************
890 * Path management messages
891 * Messages: echo and version not supported.
892 * A path is connection between two UDP/IP endpoints
893 *
894 * A path is either using GTP0 or GTP1. A path can be
895 * established by any kind of GTP message??
896
897 * Which source port to use?
898 * GTP-C request destination port is 2123/3386
899 * GTP-U request destination port is 2152/3386
900 * T-PDU destination port is 2152/3386.
901 * For the above messages the source port is locally allocated.
902 * For response messages src=rx-dst and dst=rx-src.
903 * For simplicity we should probably use 2123+2152/3386 as
904 * src port even for the cases where src can be locally
905 * allocated. This also means that we have to listen only to
906 * the same ports.
907 * For response messages we need to be able to respond to
908 * the relevant src port even if it is locally allocated by
909 * the peer.
910 *
911 * The need for path management!
912 * We might need to keep a list of active paths. This might
913 * be in the form of remote IP address + UDP port numbers.
914 * (We will consider a path astablished if we have a context
915 * with the node in question)
916 *************************************************************/
917
918/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000919int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
920 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000921{
Harald Weltebed35df2011-11-02 13:06:18 +0100922 union gtp_packet packet;
923 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
924 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000925}
926
jjako08d331d2003-10-13 20:33:30 +0000927/* Send off an echo reply */
928int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100929 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000930{
Harald Weltebed35df2011-11-02 13:06:18 +0100931 union gtp_packet packet;
932 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
933 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
934 gsn->restart_counter);
935 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
936 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000937}
938
jjako52c24142002-12-16 13:33:51 +0000939/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100940int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
941 int fd, void *pack, unsigned len)
942{
jjako52c24142002-12-16 13:33:51 +0000943
Harald Weltebed35df2011-11-02 13:06:18 +0100944 /* Check if it was a dublicate request */
945 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
946 return 0;
jjako52c24142002-12-16 13:33:51 +0000947
Harald Weltebed35df2011-11-02 13:06:18 +0100948 /* Send off reply to request */
949 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000950}
951
952/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000953int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100954 void *pack, unsigned len)
955{
956 union gtpie_member *ie[GTPIE_SIZE];
957 unsigned char recovery;
958 void *cbp = NULL;
959 uint8_t type = 0;
960 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000961
Harald Weltebed35df2011-11-02 13:06:18 +0100962 /* Remove packet from queue */
963 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
964 return EOF;
jjako52c24142002-12-16 13:33:51 +0000965
Harald Weltebed35df2011-11-02 13:06:18 +0100966 /* Extract information elements into a pointer array */
967 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
968 gsn->invalid++;
969 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
970 "Invalid message format");
971 if (gsn->cb_conf)
972 gsn->cb_conf(type, EOF, NULL, cbp);
973 return EOF;
974 }
jjako52c24142002-12-16 13:33:51 +0000975
Harald Weltebed35df2011-11-02 13:06:18 +0100976 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
977 gsn->missing++;
978 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
979 "Missing mandatory field");
980 if (gsn->cb_conf)
981 gsn->cb_conf(type, EOF, NULL, cbp);
982 return EOF;
983 }
jjako52c24142002-12-16 13:33:51 +0000984
Harald Weltebed35df2011-11-02 13:06:18 +0100985 /* Echo reply packages does not have a cause information element */
986 /* Instead we return the recovery number in the callback function */
987 if (gsn->cb_conf)
988 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100989
Harald Weltebed35df2011-11-02 13:06:18 +0100990 if (gsn->cb_recovery)
991 gsn->cb_recovery(peer, recovery);
992
993 return 0;
jjako52c24142002-12-16 13:33:51 +0000994}
995
996/* Send off a Version Not Supported message */
997/* This message is somewhat special in that it actually is a
998 * response to some other message with unsupported GTP version
999 * For this reason it has parameters like a response, and does
1000 * its own message transmission. No signalling queue is used
1001 * The reply is sent to the peer IP and peer UDP. This means that
1002 * the peer will be receiving a GTP0 message on a GTP1 port!
1003 * In practice however this will never happen as a GTP0 GSN will
1004 * only listen to the GTP0 port, and therefore will never receive
1005 * anything else than GTP0 */
1006
jjako08d331d2003-10-13 20:33:30 +00001007int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1008 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001009{
Harald Weltebed35df2011-11-02 13:06:18 +01001010 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001011
Harald Weltebed35df2011-11-02 13:06:18 +01001012 /* GTP 1 is the highest supported protocol */
1013 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1014 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001015}
1016
1017/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001018int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1019 void *pack, unsigned len)
1020{
jjako52c24142002-12-16 13:33:51 +00001021
Harald Weltebed35df2011-11-02 13:06:18 +01001022 if (gsn->cb_unsup_ind)
1023 gsn->cb_unsup_ind(peer);
1024
1025 return 0;
jjako52c24142002-12-16 13:33:51 +00001026}
1027
jjako2c381332003-10-21 19:09:53 +00001028/* Send off an Supported Extension Headers Notification */
1029int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1030 int fd, void *pack, unsigned len)
1031{
Harald Weltebed35df2011-11-02 13:06:18 +01001032 union gtp_packet packet;
1033 unsigned int length =
1034 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001035
Harald Weltebed35df2011-11-02 13:06:18 +01001036 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001037
Harald Weltebed35df2011-11-02 13:06:18 +01001038 if (version < 1)
1039 return 0;
jjako2c381332003-10-21 19:09:53 +00001040
Harald Weltebed35df2011-11-02 13:06:18 +01001041 /* We report back that we support only PDCP PDU headers */
1042 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1043 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001044
Harald Weltebed35df2011-11-02 13:06:18 +01001045 return gtp_notification(gsn, version, &packet, length,
1046 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001047}
1048
1049/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +01001050int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1051 void *pack, unsigned len)
1052{
jjako2c381332003-10-21 19:09:53 +00001053
Harald Weltebed35df2011-11-02 13:06:18 +01001054 if (gsn->cb_extheader_ind)
1055 gsn->cb_extheader_ind(peer);
1056
1057 return 0;
jjako2c381332003-10-21 19:09:53 +00001058}
1059
jjako52c24142002-12-16 13:33:51 +00001060/* ***********************************************************
1061 * Session management messages
1062 * Messages: create, update and delete PDP context
1063 *
1064 * Information storage
1065 * Information storage for each PDP context is defined in
1066 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1067 * PDP-address (IP address), sequence numbers, charging ID.
1068 * For the SGSN it also includes radio related mobility
1069 * information.
1070 *************************************************************/
1071
Harald Welte7b3347b2010-05-15 12:18:46 +02001072/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001073extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1074 void *cbp)
1075{
1076 union gtp_packet packet;
1077 unsigned int length =
1078 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1079 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001080
Harald Weltebed35df2011-11-02 13:06:18 +01001081 /* TODO: Secondary PDP Context Activation Procedure */
1082 /* In secondary activation procedure the PDP context is identified
1083 by tei in the header. The following fields are omitted: Selection
1084 mode, IMSI, MSISDN, End User Address, Access Point Name and
1085 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001086
Harald Weltebed35df2011-11-02 13:06:18 +01001087 if (pdp->secondary) {
1088 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
1089 gtp_err(LOG_ERR, __FILE__, __LINE__,
1090 "Unknown linked PDP context");
1091 return EOF;
1092 }
1093 }
jjako2c381332003-10-21 19:09:53 +00001094
Harald Weltebed35df2011-11-02 13:06:18 +01001095 if (pdp->version == 0) {
1096 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1097 sizeof(pdp->qos_req0), pdp->qos_req0);
1098 }
jjako52c24142002-12-16 13:33:51 +00001099
Harald Weltebed35df2011-11-02 13:06:18 +01001100 /* Section 7.7.2 */
1101 if (pdp->version == 1) {
1102 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1103 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1104 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1105 }
jjako52c24142002-12-16 13:33:51 +00001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 /* Section 7.7.3 Routing Area Information */
1108 if (pdp->rai_given == 1)
1109 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1110 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 /* Section 7.7.11 */
1113 if (pdp->norecovery_given == 0)
1114 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1115 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 /* Section 7.7.12 */
1118 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1119 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1120 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001121
Harald Weltebed35df2011-11-02 13:06:18 +01001122 if (pdp->version == 0) {
1123 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1124 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1125 }
jjako08d331d2003-10-13 20:33:30 +00001126
Harald Weltebed35df2011-11-02 13:06:18 +01001127 /* Section 7.7.13 */
1128 if (pdp->version == 1) {
1129 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1130 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001131
Harald Weltebed35df2011-11-02 13:06:18 +01001132 /* Section 7.7.14 */
1133 if (!pdp->teic_confirmed)
1134 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1135 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001136
Harald Weltebed35df2011-11-02 13:06:18 +01001137 /* Section 7.7.17 */
1138 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001139
Harald Weltebed35df2011-11-02 13:06:18 +01001140 /* Section 7.7.17 */
1141 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1142 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1143 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001144
Harald Weltebed35df2011-11-02 13:06:18 +01001145 /* Section 7.7.23 */
1146 if (pdp->cch_pdp) /* Only include charging if flags are set */
1147 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1148 pdp->cch_pdp);
1149 }
jjako9b4971d2004-05-27 20:30:19 +00001150
Harald Weltebed35df2011-11-02 13:06:18 +01001151 /* TODO
1152 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1153 pdp->traceref);
1154 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1155 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001156
Harald Weltebed35df2011-11-02 13:06:18 +01001157 /* Section 7.7.27 */
1158 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1159 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1160 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001161
Harald Weltebed35df2011-11-02 13:06:18 +01001162 /* Section 7.7.30 */
1163 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1164 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1165 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001166
Harald Weltebed35df2011-11-02 13:06:18 +01001167 /* Section 7.7.31 */
1168 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1169 if (pdp->pco_req.l)
1170 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1171 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001172
Harald Weltebed35df2011-11-02 13:06:18 +01001173 /* Section 7.7.32 */
1174 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1175 pdp->gsnlc.l, pdp->gsnlc.v);
1176 /* Section 7.7.32 */
1177 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1178 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001179
Harald Weltebed35df2011-11-02 13:06:18 +01001180 /* Section 7.7.33 */
1181 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1182 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1183 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001184
Harald Weltebed35df2011-11-02 13:06:18 +01001185 /* Section 7.7.34 */
1186 if (pdp->version == 1)
1187 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1188 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001189
Harald Weltebed35df2011-11-02 13:06:18 +01001190 /* Section 7.7.36 */
1191 if ((pdp->version == 1) && pdp->tft.l)
1192 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1193 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 /* Section 7.7.41 */
1196 if ((pdp->version == 1) && pdp->triggerid.l)
1197 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1198 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001199
Harald Weltebed35df2011-11-02 13:06:18 +01001200 /* Section 7.7.42 */
1201 if ((pdp->version == 1) && pdp->omcid.l)
1202 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1203 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001204
Harald Weltebed35df2011-11-02 13:06:18 +01001205 /* new R7 fields */
1206 if (pdp->rattype_given == 1)
1207 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1208 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001209
Harald Weltebed35df2011-11-02 13:06:18 +01001210 if (pdp->userloc_given == 1)
1211 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1212 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001213
Harald Weltebed35df2011-11-02 13:06:18 +01001214 if (pdp->mstz_given == 1)
1215 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1216 pdp->mstz.l, pdp->mstz.v);
1217
1218 if (pdp->imeisv_given == 1)
1219 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1220 pdp->imeisv.l, pdp->imeisv.v);
1221
1222 /* TODO hisaddr0 */
1223 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1224
1225 return 0;
jjako52c24142002-12-16 13:33:51 +00001226}
1227
jjako08d331d2003-10-13 20:33:30 +00001228/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001229int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1230{
jjako08d331d2003-10-13 20:33:30 +00001231
Harald Weltebed35df2011-11-02 13:06:18 +01001232 /* Now send off a reply to the peer */
1233 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1234
1235 if (cause != GTPCAUSE_ACC_REQ) {
1236 pdp_freepdp(pdp);
1237 }
1238
1239 return 0;
jjako08d331d2003-10-13 20:33:30 +00001240}
1241
1242/* API: Register create context indication callback */
1243int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001244 int (*cb_create_context_ind) (struct pdp_t *
1245 pdp))
jjako52c24142002-12-16 13:33:51 +00001246{
Harald Weltebed35df2011-11-02 13:06:18 +01001247 gsn->cb_create_context_ind = cb_create_context_ind;
1248 return 0;
jjako08d331d2003-10-13 20:33:30 +00001249}
1250
jjako08d331d2003-10-13 20:33:30 +00001251/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001252int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1253 uint8_t cause)
1254{
1255 union gtp_packet packet;
1256 unsigned int length =
1257 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001258
Harald Weltebed35df2011-11-02 13:06:18 +01001259 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001260
Harald Weltebed35df2011-11-02 13:06:18 +01001261 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001262
Harald Weltebed35df2011-11-02 13:06:18 +01001263 if (version == 0)
1264 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1265 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001266
Harald Weltebed35df2011-11-02 13:06:18 +01001267 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1268 pdp->reorder);
1269 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1270 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001271
Harald Weltebed35df2011-11-02 13:06:18 +01001272 if (version == 0) {
1273 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1274 pdp->fllu);
1275 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1276 pdp->fllc);
1277 }
jjako08d331d2003-10-13 20:33:30 +00001278
Harald Weltebed35df2011-11-02 13:06:18 +01001279 if (version == 1) {
1280 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1281 pdp->teid_own);
1282 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1283 pdp->teic_own);
1284 }
jjako08d331d2003-10-13 20:33:30 +00001285
Harald Weltebed35df2011-11-02 13:06:18 +01001286 /* TODO: We use teic_own as charging ID */
1287 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1288 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001289
Harald Weltebed35df2011-11-02 13:06:18 +01001290 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1291 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001292
Harald Weltebed35df2011-11-02 13:06:18 +01001293 if (pdp->pco_neg.l) { /* Optional PCO */
1294 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1295 pdp->pco_neg.l, pdp->pco_neg.v);
1296 }
jjako52c24142002-12-16 13:33:51 +00001297
Harald Weltebed35df2011-11-02 13:06:18 +01001298 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1299 pdp->gsnlc.l, pdp->gsnlc.v);
1300 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1301 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001302
Harald Weltebed35df2011-11-02 13:06:18 +01001303 if (version == 1)
1304 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1305 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001306
Harald Weltebed35df2011-11-02 13:06:18 +01001307 /* TODO: Charging gateway address */
1308 }
jjako52c24142002-12-16 13:33:51 +00001309
Harald Weltebed35df2011-11-02 13:06:18 +01001310 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1311 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001312}
1313
1314/* Handle Create PDP Context Request */
1315int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001316 struct sockaddr_in *peer, int fd,
1317 void *pack, unsigned len)
1318{
1319 struct pdp_t *pdp, *pdp_old;
1320 struct pdp_t pdp_buf;
1321 union gtpie_member *ie[GTPIE_SIZE];
1322 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001323
Harald Weltebed35df2011-11-02 13:06:18 +01001324 uint16_t seq = get_seq(pack);
1325 int hlen = get_hlen(pack);
1326 uint8_t linked_nsapi = 0;
1327 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001328
Harald Weltebed35df2011-11-02 13:06:18 +01001329 if (!gtp_dublicate(gsn, version, peer, seq))
1330 return 0;
jjako08d331d2003-10-13 20:33:30 +00001331
Harald Weltebed35df2011-11-02 13:06:18 +01001332 pdp = &pdp_buf;
1333 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001334
Harald Weltebed35df2011-11-02 13:06:18 +01001335 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001336 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1337
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001338 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001339 }
jjako52c24142002-12-16 13:33:51 +00001340
Harald Weltebed35df2011-11-02 13:06:18 +01001341 pdp->seq = seq;
1342 pdp->sa_peer = *peer;
1343 pdp->fd = fd;
1344 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001345
Harald Weltebed35df2011-11-02 13:06:18 +01001346 /* Decode information elements */
1347 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1348 gsn->invalid++;
1349 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1350 "Invalid message format");
1351 if (0 == version)
1352 return EOF;
1353 else
1354 return gtp_create_pdp_resp(gsn, version, pdp,
1355 GTPCAUSE_INVALID_MESSAGE);
1356 }
jjako52c24142002-12-16 13:33:51 +00001357
Harald Weltebed35df2011-11-02 13:06:18 +01001358 if (version == 1) {
1359 /* Linked NSAPI (conditional) */
1360 /* If included this is the Secondary PDP Context Activation Procedure */
1361 /* In secondary activation IMSI is not included, so the context must be */
1362 /* identified by the tei */
1363 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001364
Harald Weltebed35df2011-11-02 13:06:18 +01001365 /* Find the primary PDP context */
1366 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1367 gsn->incorrect++;
1368 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1369 pack, len,
1370 "Incorrect optional information field");
1371 return gtp_create_pdp_resp(gsn, version, pdp,
1372 GTPCAUSE_OPT_IE_INCORRECT);
1373 }
jjako2c381332003-10-21 19:09:53 +00001374
Harald Weltebed35df2011-11-02 13:06:18 +01001375 /* Check that the primary PDP context matches linked nsapi */
1376 if (linked_pdp->nsapi != linked_nsapi) {
1377 gsn->incorrect++;
1378 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1379 pack, len,
1380 "Incorrect optional information field");
1381 return gtp_create_pdp_resp(gsn, version, pdp,
1382 GTPCAUSE_OPT_IE_INCORRECT);
1383 }
jjako52c24142002-12-16 13:33:51 +00001384
Harald Weltebed35df2011-11-02 13:06:18 +01001385 /* Copy parameters from primary context */
1386 pdp->selmode = linked_pdp->selmode;
1387 pdp->imsi = linked_pdp->imsi;
1388 pdp->msisdn = linked_pdp->msisdn;
1389 pdp->eua = linked_pdp->eua;
1390 pdp->pco_req = linked_pdp->pco_req;
1391 pdp->apn_req = linked_pdp->apn_req;
1392 pdp->teic_gn = linked_pdp->teic_gn;
1393 pdp->secondary = 1;
1394 }
1395 }
1396 /* if (version == 1) */
1397 if (version == 0) {
1398 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1399 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1400 gsn->missing++;
1401 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1402 len, "Missing mandatory information field");
1403 return gtp_create_pdp_resp(gsn, version, pdp,
1404 GTPCAUSE_MAN_IE_MISSING);
1405 }
1406 }
jjako08d331d2003-10-13 20:33:30 +00001407
Harald Weltebed35df2011-11-02 13:06:18 +01001408 if ((version == 1) && (!linked_pdp)) {
1409 /* Not Secondary PDP Context Activation Procedure */
1410 /* IMSI (conditional) */
1411 if (gtpie_gettv0
1412 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1413 gsn->missing++;
1414 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1415 len, "Missing mandatory information field");
1416 return gtp_create_pdp_resp(gsn, version, pdp,
1417 GTPCAUSE_MAN_IE_MISSING);
1418 }
1419 }
jjako52c24142002-12-16 13:33:51 +00001420
Harald Weltebed35df2011-11-02 13:06:18 +01001421 /* Recovery (optional) */
1422 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1423 if (gsn->cb_recovery)
1424 gsn->cb_recovery(peer, recovery);
1425 }
jjako52c24142002-12-16 13:33:51 +00001426
Harald Weltebed35df2011-11-02 13:06:18 +01001427 /* Selection mode (conditional) */
1428 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1429 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1430 &pdp->selmode, sizeof(pdp->selmode))) {
1431 gsn->missing++;
1432 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1433 len, "Missing mandatory information field");
1434 return gtp_create_pdp_resp(gsn, version, pdp,
1435 GTPCAUSE_MAN_IE_MISSING);
1436 }
1437 }
jjako52c24142002-12-16 13:33:51 +00001438
Harald Weltebed35df2011-11-02 13:06:18 +01001439 if (version == 0) {
1440 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1441 gsn->missing++;
1442 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1443 len, "Missing mandatory information field");
1444 return gtp_create_pdp_resp(gsn, version, pdp,
1445 GTPCAUSE_MAN_IE_MISSING);
1446 }
jjako52c24142002-12-16 13:33:51 +00001447
Harald Weltebed35df2011-11-02 13:06:18 +01001448 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1449 gsn->missing++;
1450 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1451 len, "Missing mandatory information field");
1452 return gtp_create_pdp_resp(gsn, version, pdp,
1453 GTPCAUSE_MAN_IE_MISSING);
1454 }
1455 }
jjako08d331d2003-10-13 20:33:30 +00001456
Harald Weltebed35df2011-11-02 13:06:18 +01001457 if (version == 1) {
1458 /* TEID (mandatory) */
1459 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1460 gsn->missing++;
1461 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1462 len, "Missing mandatory information field");
1463 return gtp_create_pdp_resp(gsn, version, pdp,
1464 GTPCAUSE_MAN_IE_MISSING);
1465 }
jjako2c381332003-10-21 19:09:53 +00001466
Harald Weltebed35df2011-11-02 13:06:18 +01001467 /* TEIC (conditional) */
1468 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1469 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1470 gsn->missing++;
1471 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1472 pack, len,
1473 "Missing mandatory information field");
1474 return gtp_create_pdp_resp(gsn, version, pdp,
1475 GTPCAUSE_MAN_IE_MISSING);
1476 }
1477 }
jjako08d331d2003-10-13 20:33:30 +00001478
Harald Weltebed35df2011-11-02 13:06:18 +01001479 /* NSAPI (mandatory) */
1480 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1481 gsn->missing++;
1482 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1483 len, "Missing mandatory information field");
1484 return gtp_create_pdp_resp(gsn, version, pdp,
1485 GTPCAUSE_MAN_IE_MISSING);
1486 }
1487 }
jjako2e840a32003-01-28 16:05:18 +00001488
Harald Weltebed35df2011-11-02 13:06:18 +01001489 /* Charging Characteriatics (optional) */
1490 /* Trace reference (optional) */
1491 /* Trace type (optional) */
1492 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001493
Harald Weltebed35df2011-11-02 13:06:18 +01001494 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1495 /* End User Address (conditional) */
1496 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1497 &pdp->eua.v, sizeof(pdp->eua.v))) {
1498 gsn->missing++;
1499 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1500 len, "Missing mandatory information field");
1501 return gtp_create_pdp_resp(gsn, version, pdp,
1502 GTPCAUSE_MAN_IE_MISSING);
1503 }
jjako08d331d2003-10-13 20:33:30 +00001504
Harald Weltebed35df2011-11-02 13:06:18 +01001505 /* APN */
1506 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1507 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1508 gsn->missing++;
1509 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1510 len, "Missing mandatory information field");
1511 return gtp_create_pdp_resp(gsn, version, pdp,
1512 GTPCAUSE_MAN_IE_MISSING);
1513 }
jjako2c381332003-10-21 19:09:53 +00001514
Harald Weltebed35df2011-11-02 13:06:18 +01001515 /* Extract protocol configuration options (optional) */
1516 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1517 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1518 }
1519 }
jjako2c381332003-10-21 19:09:53 +00001520
Harald Weltebed35df2011-11-02 13:06:18 +01001521 /* SGSN address for signalling (mandatory) */
1522 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1523 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1524 gsn->missing++;
1525 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1526 "Missing mandatory information field");
1527 return gtp_create_pdp_resp(gsn, version, pdp,
1528 GTPCAUSE_MAN_IE_MISSING);
1529 }
jjako2e840a32003-01-28 16:05:18 +00001530
Harald Weltebed35df2011-11-02 13:06:18 +01001531 /* SGSN address for user traffic (mandatory) */
1532 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1533 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1534 gsn->missing++;
1535 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1536 "Missing mandatory information field");
1537 return gtp_create_pdp_resp(gsn, version, pdp,
1538 GTPCAUSE_MAN_IE_MISSING);
1539 }
jjako52c24142002-12-16 13:33:51 +00001540
Harald Weltebed35df2011-11-02 13:06:18 +01001541 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1542 /* MSISDN (conditional) */
1543 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1544 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1545 gsn->missing++;
1546 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1547 len, "Missing mandatory information field");
1548 return gtp_create_pdp_resp(gsn, version, pdp,
1549 GTPCAUSE_MAN_IE_MISSING);
1550 }
1551 }
jjako52c24142002-12-16 13:33:51 +00001552
Harald Weltebed35df2011-11-02 13:06:18 +01001553 if (version == 1) {
1554 /* QoS (mandatory) */
1555 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1556 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1557 gsn->missing++;
1558 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1559 len, "Missing mandatory information field");
1560 return gtp_create_pdp_resp(gsn, version, pdp,
1561 GTPCAUSE_MAN_IE_MISSING);
1562 }
1563
1564 /* TFT (conditional) */
1565 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1566 &pdp->tft.v, sizeof(pdp->tft.v))) {
1567 }
1568
1569 /* Trigger ID */
1570 /* OMC identity */
1571 }
1572
1573 /* Initialize our own IP addresses */
1574 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1575 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1576
1577 if (GTP_DEBUG)
1578 printf("gtp_create_pdp_ind: Before pdp_tidget\n");
1579
1580 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1581 /* Found old pdp with same tid. Now the voodoo begins! */
1582 /* 09.60 / 29.060 allows create on existing context to "steal" */
1583 /* the context which was allready established */
1584 /* We check that the APN, selection mode and MSISDN is the same */
1585 if (GTP_DEBUG)
1586 printf("gtp_create_pdp_ind: Old context found\n");
1587 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1588 &&
1589 (!memcmp
1590 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1591 && (pdp->selmode == pdp_old->selmode)
1592 && (pdp->msisdn.l == pdp_old->msisdn.l)
1593 &&
1594 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1595 {
1596 /* OK! We are dealing with the same APN. We will copy new
1597 * parameters to the old pdp and send off confirmation
1598 * We ignore the following information elements:
1599 * QoS: MS will get originally negotiated QoS.
1600 * End user address (EUA). MS will get old EUA anyway.
1601 * Protocol configuration option (PCO): Only application can verify */
1602
1603 if (GTP_DEBUG)
1604 printf
1605 ("gtp_create_pdp_ind: Old context found\n");
1606
1607 /* Copy remote flow label */
1608 pdp_old->flru = pdp->flru;
1609 pdp_old->flrc = pdp->flrc;
1610
1611 /* Copy remote tei */
1612 pdp_old->teid_gn = pdp->teid_gn;
1613 pdp_old->teic_gn = pdp->teic_gn;
1614
1615 /* Copy peer GSN address */
1616 pdp_old->gsnrc.l = pdp->gsnrc.l;
1617 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1618 pdp_old->gsnru.l = pdp->gsnru.l;
1619 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1620
1621 /* Copy request parameters */
1622 pdp_old->seq = pdp->seq;
1623 pdp_old->sa_peer = pdp->sa_peer;
1624 pdp_old->fd = pdp->fd = fd;
1625 pdp_old->version = pdp->version = version;
1626
1627 /* Switch to using the old pdp context */
1628 pdp = pdp_old;
1629
1630 /* Confirm to peer that things were "successful" */
1631 return gtp_create_pdp_resp(gsn, version, pdp,
1632 GTPCAUSE_ACC_REQ);
1633 } else { /* This is not the same PDP context. Delete the old one. */
1634
1635 if (GTP_DEBUG)
1636 printf
1637 ("gtp_create_pdp_ind: Deleting old context\n");
1638
1639 if (gsn->cb_delete_context)
1640 gsn->cb_delete_context(pdp_old);
1641 pdp_freepdp(pdp_old);
1642
1643 if (GTP_DEBUG)
1644 printf("gtp_create_pdp_ind: Deleted...\n");
1645 }
1646 }
1647
1648 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1649
1650 /* Callback function to validata login */
1651 if (gsn->cb_create_context_ind != 0)
1652 return gsn->cb_create_context_ind(pdp);
1653 else {
1654 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1655 "No create_context_ind callback defined");
1656 return gtp_create_pdp_resp(gsn, version, pdp,
1657 GTPCAUSE_NOT_SUPPORTED);
1658 }
jjako52c24142002-12-16 13:33:51 +00001659}
1660
jjako52c24142002-12-16 13:33:51 +00001661/* Handle Create PDP Context Response */
1662int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001663 struct sockaddr_in *peer, void *pack, unsigned len)
1664{
1665 struct pdp_t *pdp;
1666 union gtpie_member *ie[GTPIE_SIZE];
1667 uint8_t cause, recovery;
1668 void *cbp = NULL;
1669 uint8_t type = 0;
1670 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001671
Harald Weltebed35df2011-11-02 13:06:18 +01001672 /* Remove packet from queue */
1673 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1674 return EOF;
jjako52c24142002-12-16 13:33:51 +00001675
Harald Weltebed35df2011-11-02 13:06:18 +01001676 /* Find the context in question */
1677 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1678 gsn->err_unknownpdp++;
1679 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1680 "Unknown PDP context");
1681 if (gsn->cb_conf)
1682 gsn->cb_conf(type, EOF, NULL, cbp);
1683 return EOF;
1684 }
jjako2c381332003-10-21 19:09:53 +00001685
Harald Weltebed35df2011-11-02 13:06:18 +01001686 /* Register that we have received a valid teic from GGSN */
1687 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001688
Harald Weltebed35df2011-11-02 13:06:18 +01001689 /* Decode information elements */
1690 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1691 gsn->invalid++;
1692 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1693 "Invalid message format");
1694 if (gsn->cb_conf)
1695 gsn->cb_conf(type, EOF, pdp, cbp);
1696 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1697 pdp_freepdp(pdp); */
1698 return EOF;
1699 }
jjako52c24142002-12-16 13:33:51 +00001700
Harald Weltebed35df2011-11-02 13:06:18 +01001701 /* Extract cause value (mandatory) */
1702 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1703 gsn->missing++;
1704 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1705 "Missing mandatory information field");
1706 if (gsn->cb_conf)
1707 gsn->cb_conf(type, EOF, pdp, cbp);
1708 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1709 pdp_freepdp(pdp); */
1710 return EOF;
1711 }
jjako52c24142002-12-16 13:33:51 +00001712
Harald Weltebed35df2011-11-02 13:06:18 +01001713 /* Extract recovery (optional) */
1714 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1715 if (gsn->cb_recovery)
1716 gsn->cb_recovery(peer, recovery);
1717 }
jjako52c24142002-12-16 13:33:51 +00001718
Harald Weltebed35df2011-11-02 13:06:18 +01001719 /* Extract protocol configuration options (optional) */
1720 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1721 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1722 }
jjako52c24142002-12-16 13:33:51 +00001723
Harald Weltebed35df2011-11-02 13:06:18 +01001724 /* Check all conditional information elements */
1725 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001726
Harald Weltebed35df2011-11-02 13:06:18 +01001727 if (version == 0) {
1728 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1729 &pdp->qos_neg0,
1730 sizeof(pdp->qos_neg0))) {
1731 gsn->missing++;
1732 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1733 pack, len,
1734 "Missing conditional information field");
1735 if (gsn->cb_conf)
1736 gsn->cb_conf(type, EOF, pdp, cbp);
1737 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1738 pdp_freepdp(pdp); */
1739 return EOF;
1740 }
1741 }
jjako08d331d2003-10-13 20:33:30 +00001742
Harald Weltebed35df2011-11-02 13:06:18 +01001743 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1744 gsn->missing++;
1745 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1746 len,
1747 "Missing conditional information field");
1748 if (gsn->cb_conf)
1749 gsn->cb_conf(type, EOF, pdp, cbp);
1750 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1751 pdp_freepdp(pdp); */
1752 return EOF;
1753 }
jjako52c24142002-12-16 13:33:51 +00001754
Harald Weltebed35df2011-11-02 13:06:18 +01001755 if (version == 0) {
1756 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1757 gsn->missing++;
1758 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1759 pack, len,
1760 "Missing conditional information field");
1761 if (gsn->cb_conf)
1762 gsn->cb_conf(type, EOF, pdp, cbp);
1763 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1764 pdp_freepdp(pdp); */
1765 return EOF;
1766 }
jjako52c24142002-12-16 13:33:51 +00001767
Harald Weltebed35df2011-11-02 13:06:18 +01001768 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1769 gsn->missing++;
1770 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1771 pack, len,
1772 "Missing conditional information field");
1773 if (gsn->cb_conf)
1774 gsn->cb_conf(type, EOF, pdp, cbp);
1775 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1776 pdp_freepdp(pdp); */
1777 return EOF;
1778 }
1779 }
1780
1781 if (version == 1) {
1782 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1783 gsn->missing++;
1784 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1785 pack, len,
1786 "Missing conditional information field");
1787 if (gsn->cb_conf)
1788 gsn->cb_conf(type, EOF, pdp, cbp);
1789 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1790 pdp_freepdp(pdp); */
1791 return EOF;
1792 }
1793
1794 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1795 gsn->missing++;
1796 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1797 pack, len,
1798 "Missing conditional information field");
1799 if (gsn->cb_conf)
1800 gsn->cb_conf(type, EOF, pdp, cbp);
1801 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1802 pdp_freepdp(pdp); */
1803 return EOF;
1804 }
1805 }
1806
1807 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1808 gsn->missing++;
1809 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1810 len,
1811 "Missing conditional information field");
1812 if (gsn->cb_conf)
1813 gsn->cb_conf(type, EOF, pdp, cbp);
1814 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1815 pdp_freepdp(pdp); */
1816 }
1817
1818 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1819 &pdp->eua.v, sizeof(pdp->eua.v))) {
1820 gsn->missing++;
1821 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1822 len,
1823 "Missing conditional information field");
1824 if (gsn->cb_conf)
1825 gsn->cb_conf(type, EOF, pdp, cbp);
1826 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1827 pdp_freepdp(pdp); */
1828 return EOF;
1829 }
1830
1831 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1832 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1833 gsn->missing++;
1834 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1835 len,
1836 "Missing conditional information field");
1837 if (gsn->cb_conf)
1838 gsn->cb_conf(type, EOF, pdp, cbp);
1839 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1840 pdp_freepdp(pdp); */
1841 return EOF;
1842 }
1843
1844 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1845 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1846 gsn->missing++;
1847 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1848 len,
1849 "Missing conditional information field");
1850 if (gsn->cb_conf)
1851 gsn->cb_conf(type, EOF, pdp, cbp);
1852 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1853 pdp_freepdp(pdp); */
1854 return EOF;
1855 }
1856
1857 if (version == 1) {
1858 if (gtpie_gettlv
1859 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1860 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1861 gsn->missing++;
1862 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1863 pack, len,
1864 "Missing conditional information field");
1865 if (gsn->cb_conf)
1866 gsn->cb_conf(type, EOF, pdp, cbp);
1867 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1868 pdp_freepdp(pdp); */
1869 return EOF;
1870 }
1871 }
1872
1873 }
1874
1875 if (gsn->cb_conf)
1876 gsn->cb_conf(type, cause, pdp, cbp);
1877
1878 return 0;
jjako52c24142002-12-16 13:33:51 +00001879}
1880
jjako08d331d2003-10-13 20:33:30 +00001881/* API: Send Update PDP Context Request */
1882int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001883 struct in_addr *inetaddr)
1884{
1885 union gtp_packet packet;
1886 unsigned int length =
1887 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001888
Harald Weltebed35df2011-11-02 13:06:18 +01001889 if (pdp->version == 0)
1890 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1891 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001892
Harald Weltebed35df2011-11-02 13:06:18 +01001893 /* Include IMSI if updating with unknown teic_gn */
1894 if ((pdp->version == 1) && (!pdp->teic_gn))
1895 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1896 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1897
1898 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1899 gsn->restart_counter);
1900
1901 if (pdp->version == 0) {
1902 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1903 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1904 }
1905
1906 if (pdp->version == 1) {
1907 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1908 pdp->teid_own);
1909
1910 if (!pdp->teic_confirmed)
1911 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1912 pdp->teic_own);
1913 }
1914
1915 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1916
1917 /* TODO
1918 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1919 pdp->traceref);
1920 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1921 pdp->tracetype); */
1922
1923 /* TODO if ggsn update message
1924 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1925 pdp->eua.l, pdp->eua.v);
1926 */
1927
1928 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1929 pdp->gsnlc.l, pdp->gsnlc.v);
1930 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1931 pdp->gsnlu.l, pdp->gsnlu.v);
1932
1933 if (pdp->version == 1)
1934 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1935 pdp->qos_req.l, pdp->qos_req.v);
1936
1937 if ((pdp->version == 1) && pdp->tft.l)
1938 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1939 pdp->tft.l, pdp->tft.v);
1940
1941 if ((pdp->version == 1) && pdp->triggerid.l)
1942 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1943 pdp->triggerid.l, pdp->triggerid.v);
1944
1945 if ((pdp->version == 1) && pdp->omcid.l)
1946 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1947 pdp->omcid.l, pdp->omcid.v);
1948
1949 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1950
1951 return 0;
jjako52c24142002-12-16 13:33:51 +00001952}
1953
jjako08d331d2003-10-13 20:33:30 +00001954/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001955int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1956 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001957 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001958 struct pdp_t *pdp, uint8_t cause)
1959{
jjako08d331d2003-10-13 20:33:30 +00001960
Harald Weltebed35df2011-11-02 13:06:18 +01001961 union gtp_packet packet;
1962 unsigned int length =
1963 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001964
Harald Weltebed35df2011-11-02 13:06:18 +01001965 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001966
Harald Weltebed35df2011-11-02 13:06:18 +01001967 if (cause == GTPCAUSE_ACC_REQ) {
1968
1969 if (version == 0)
1970 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1971 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1972
1973 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1974 gsn->restart_counter);
1975
1976 if (version == 0) {
1977 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1978 pdp->fllu);
1979 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1980 pdp->fllc);
1981 }
1982
1983 if (version == 1) {
1984 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1985 pdp->teid_own);
1986
1987 if (!pdp->teic_confirmed)
1988 gtpie_tv4(&packet, &length, GTP_MAX,
1989 GTPIE_TEI_C, pdp->teic_own);
1990 }
1991
1992 /* TODO we use teid_own as charging ID address */
1993 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1994 pdp->teid_own);
1995
1996 /* If ggsn
1997 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1998 pdp->eua.l, pdp->eua.v); */
1999
2000 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2001 pdp->gsnlc.l, pdp->gsnlc.v);
2002 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2003 pdp->gsnlu.l, pdp->gsnlu.v);
2004
2005 if (version == 1)
2006 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2007 pdp->qos_neg.l, pdp->qos_neg.v);
2008
2009 /* TODO: Charging gateway address */
2010 }
2011
2012 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2013 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002014}
2015
jjako52c24142002-12-16 13:33:51 +00002016/* Handle Update PDP Context Request */
2017int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002018 struct sockaddr_in *peer, int fd,
2019 void *pack, unsigned len)
2020{
2021 struct pdp_t *pdp;
2022 struct pdp_t pdp_backup;
2023 union gtpie_member *ie[GTPIE_SIZE];
2024 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002025
Harald Weltebed35df2011-11-02 13:06:18 +01002026 uint16_t seq = get_seq(pack);
2027 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002028
Harald Weltebed35df2011-11-02 13:06:18 +01002029 uint64_t imsi;
2030 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002031
Harald Weltebed35df2011-11-02 13:06:18 +01002032 /* Is this a dublicate ? */
2033 if (!gtp_dublicate(gsn, version, peer, seq)) {
2034 return 0; /* We allready send of response once */
2035 }
jjako08d331d2003-10-13 20:33:30 +00002036
Harald Weltebed35df2011-11-02 13:06:18 +01002037 /* Decode information elements */
2038 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2039 gsn->invalid++;
2040 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2041 "Invalid message format");
2042 if (0 == version)
2043 return EOF;
2044 else
2045 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2046 len, NULL,
2047 GTPCAUSE_INVALID_MESSAGE);
2048 }
jjako08d331d2003-10-13 20:33:30 +00002049
Harald Weltebed35df2011-11-02 13:06:18 +01002050 /* Finding PDP: */
2051 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2052 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2053 /* we have to use the tunnel endpoint identifier */
2054 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002055 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2056
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002057 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002058
Harald Weltebed35df2011-11-02 13:06:18 +01002059 /* Find the context in question */
2060 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2061 gsn->err_unknownpdp++;
2062 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2063 len, "Unknown PDP context");
2064 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2065 len, NULL,
2066 GTPCAUSE_NON_EXIST);
2067 }
2068 } else if (version == 1) {
2069 /* NSAPI (mandatory) */
2070 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2071 gsn->missing++;
2072 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2073 len, "Missing mandatory information field");
2074 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2075 len, NULL,
2076 GTPCAUSE_MAN_IE_MISSING);
2077 }
jjako08d331d2003-10-13 20:33:30 +00002078
Harald Weltebed35df2011-11-02 13:06:18 +01002079 /* IMSI (conditional) */
2080 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2081 /* Find the context in question */
2082 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2083 gsn->err_unknownpdp++;
2084 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
2085 pack, len, "Unknown PDP context");
2086 return gtp_update_pdp_resp(gsn, version, peer,
2087 fd, pack, len, NULL,
2088 GTPCAUSE_NON_EXIST);
2089 }
2090 } else {
2091 /* Find the context in question */
2092 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2093 gsn->err_unknownpdp++;
2094 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
2095 pack, len, "Unknown PDP context");
2096 return gtp_update_pdp_resp(gsn, version, peer,
2097 fd, pack, len, NULL,
2098 GTPCAUSE_NON_EXIST);
2099 }
2100 }
2101 } else {
2102 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
2103 return EOF;
2104 }
jjako08d331d2003-10-13 20:33:30 +00002105
Harald Weltebed35df2011-11-02 13:06:18 +01002106 /* Make a backup copy in case anything is wrong */
2107 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002108
Harald Weltebed35df2011-11-02 13:06:18 +01002109 if (version == 0) {
2110 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2111 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2112 gsn->missing++;
2113 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2114 len, "Missing mandatory information field");
2115 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2116 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2117 len, pdp,
2118 GTPCAUSE_MAN_IE_MISSING);
2119 }
2120 }
jjako52c24142002-12-16 13:33:51 +00002121
Harald Weltebed35df2011-11-02 13:06:18 +01002122 /* Recovery (optional) */
2123 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2124 if (gsn->cb_recovery)
2125 gsn->cb_recovery(peer, recovery);
2126 }
jjako08d331d2003-10-13 20:33:30 +00002127
Harald Weltebed35df2011-11-02 13:06:18 +01002128 if (version == 0) {
2129 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2130 gsn->missing++;
2131 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2132 len, "Missing mandatory information field");
2133 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2134 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2135 len, pdp,
2136 GTPCAUSE_MAN_IE_MISSING);
2137 }
jjako52c24142002-12-16 13:33:51 +00002138
Harald Weltebed35df2011-11-02 13:06:18 +01002139 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2140 gsn->missing++;
2141 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2142 len, "Missing mandatory information field");
2143 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2144 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2145 len, pdp,
2146 GTPCAUSE_MAN_IE_MISSING);
2147 }
2148 }
jjako52c24142002-12-16 13:33:51 +00002149
Harald Weltebed35df2011-11-02 13:06:18 +01002150 if (version == 1) {
2151 /* TEID (mandatory) */
2152 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2153 gsn->missing++;
2154 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2155 len, "Missing mandatory information field");
2156 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2157 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2158 len, pdp,
2159 GTPCAUSE_MAN_IE_MISSING);
2160 }
jjako52c24142002-12-16 13:33:51 +00002161
Harald Weltebed35df2011-11-02 13:06:18 +01002162 /* TEIC (conditional) */
2163 /* If TEIC is not included it means that we have allready received it */
2164 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2165 /* all updated contexts, or only for one of the linked contexts */
2166 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2167
2168 /* NSAPI (mandatory) */
2169 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2170 gsn->missing++;
2171 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2172 len, "Missing mandatory information field");
2173 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2174 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2175 len, pdp,
2176 GTPCAUSE_MAN_IE_MISSING);
2177 }
2178 }
2179
2180 /* Trace reference (optional) */
2181 /* Trace type (optional) */
2182
2183 /* End User Address (conditional) TODO: GGSN Initiated
2184 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2185 &pdp->eua.v, sizeof(pdp->eua.v))) {
2186 gsn->missing++;
2187 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2188 "Missing mandatory information field");
2189 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2190 return gtp_update_pdp_resp(gsn, version, pdp,
2191 GTPCAUSE_MAN_IE_MISSING);
2192 } */
2193
2194 /* SGSN address for signalling (mandatory) */
2195 /* It is weird that this is mandatory when TEIC is conditional */
2196 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2197 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2198 gsn->missing++;
2199 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2200 "Missing mandatory information field");
2201 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2202 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2203 pdp, GTPCAUSE_MAN_IE_MISSING);
2204 }
2205
2206 /* SGSN address for user traffic (mandatory) */
2207 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2208 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2209 gsn->missing++;
2210 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2211 "Missing mandatory information field");
2212 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2213 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2214 pdp, GTPCAUSE_MAN_IE_MISSING);
2215 }
2216
2217 if (version == 1) {
2218 /* QoS (mandatory) */
2219 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2220 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2221 gsn->missing++;
2222 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2223 len, "Missing mandatory information field");
2224 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2225 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2226 len, pdp,
2227 GTPCAUSE_MAN_IE_MISSING);
2228 }
2229
2230 /* TFT (conditional) */
2231 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2232 &pdp->tft.v, sizeof(pdp->tft.v))) {
2233 }
2234
2235 /* OMC identity */
2236 }
2237
2238 /* Confirm to peer that things were "successful" */
2239 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2240 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002241}
2242
jjako52c24142002-12-16 13:33:51 +00002243/* Handle Update PDP Context Response */
2244int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002245 struct sockaddr_in *peer, void *pack, unsigned len)
2246{
2247 struct pdp_t *pdp;
2248 union gtpie_member *ie[GTPIE_SIZE];
2249 uint8_t cause, recovery;
2250 void *cbp = NULL;
2251 uint8_t type = 0;
jjako52c24142002-12-16 13:33:51 +00002252
Harald Weltebed35df2011-11-02 13:06:18 +01002253 /* Remove packet from queue */
2254 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2255 return EOF;
jjako52c24142002-12-16 13:33:51 +00002256
Harald Weltebed35df2011-11-02 13:06:18 +01002257 /* Find the context in question */
2258 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2259 gsn->err_unknownpdp++;
2260 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2261 "Unknown PDP context");
2262 if (gsn->cb_conf)
2263 gsn->cb_conf(type, cause, NULL, cbp);
2264 return EOF;
2265 }
jjako2c381332003-10-21 19:09:53 +00002266
Harald Weltebed35df2011-11-02 13:06:18 +01002267 /* Register that we have received a valid teic from GGSN */
2268 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002269
Harald Weltebed35df2011-11-02 13:06:18 +01002270 /* Decode information elements */
2271 if (gtpie_decaps
2272 (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
2273 gsn->invalid++;
2274 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2275 "Invalid message format");
2276 if (gsn->cb_conf)
2277 gsn->cb_conf(type, EOF, pdp, cbp);
2278 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2279 pdp_freepdp(pdp); */
2280 return EOF;
2281 }
jjako52c24142002-12-16 13:33:51 +00002282
Harald Weltebed35df2011-11-02 13:06:18 +01002283 /* Extract cause value (mandatory) */
2284 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2285 gsn->missing++;
2286 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2287 "Missing mandatory information field");
2288 if (gsn->cb_conf)
2289 gsn->cb_conf(type, EOF, pdp, cbp);
2290 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2291 pdp_freepdp(pdp); */
2292 return EOF;
2293 }
jjako52c24142002-12-16 13:33:51 +00002294
Harald Weltebed35df2011-11-02 13:06:18 +01002295 /* Extract recovery (optional) */
2296 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2297 if (gsn->cb_recovery)
2298 gsn->cb_recovery(peer, recovery);
2299 }
2300
2301 /* Check all conditional information elements */
2302 if (GTPCAUSE_ACC_REQ != cause) {
2303 if (gsn->cb_conf)
2304 gsn->cb_conf(type, cause, pdp, cbp);
2305 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2306 pdp_freepdp(pdp); */
2307 return 0;
2308 } else {
2309 /* Check for missing conditionary information elements */
2310 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2311 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2312 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2313 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2314 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2315 gtpie_exist(ie, GTPIE_EUA, 0) &&
2316 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2317 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2318 gsn->missing++;
2319 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2320 len,
2321 "Missing conditional information field");
2322 if (gsn->cb_conf)
2323 gsn->cb_conf(type, EOF, pdp, cbp);
2324 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2325 pdp_freepdp(pdp); */
2326 return EOF;
2327 }
2328
2329 /* Update pdp with new values */
2330 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2331 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2332 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2333 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2334 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2335 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2336 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2337 &pdp->eua.v, sizeof(pdp->eua.v));
2338 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2339 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2340 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2341 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2342
2343 if (gsn->cb_conf)
2344 gsn->cb_conf(type, cause, pdp, cbp);
2345 return 0; /* Succes */
2346 }
jjako52c24142002-12-16 13:33:51 +00002347}
2348
jjako08d331d2003-10-13 20:33:30 +00002349/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002350int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002351 int teardown)
2352{
2353 union gtp_packet packet;
2354 unsigned int length =
2355 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2356 struct in_addr addr;
2357 struct pdp_t *linked_pdp;
2358 struct pdp_t *secondary_pdp;
2359 int n;
2360 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002361
Harald Weltebed35df2011-11-02 13:06:18 +01002362 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2363 gsn->err_address++;
2364 gtp_err(LOG_ERR, __FILE__, __LINE__,
2365 "GSN address conversion failed");
2366 return EOF;
jjako2c381332003-10-21 19:09:53 +00002367 }
jjako2c381332003-10-21 19:09:53 +00002368
Harald Weltebed35df2011-11-02 13:06:18 +01002369 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2370 gtp_err(LOG_ERR, __FILE__, __LINE__,
2371 "Unknown linked PDP context");
2372 return EOF;
2373 }
2374
2375 if (!teardown) {
2376 for (n = 0; n < PDP_MAXNSAPI; n++)
2377 if (linked_pdp->secondary_tei[n])
2378 count++;
2379 if (count <= 1) {
2380 gtp_err(LOG_ERR, __FILE__, __LINE__,
2381 "Must use teardown for last context");
2382 return EOF;
2383 }
2384 }
2385
2386 if (pdp->version == 1) {
2387 if (teardown)
2388 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2389 0xff);
2390
2391 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2392 }
2393
2394 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2395
2396 if (teardown) { /* Remove all contexts */
2397 for (n = 0; n < PDP_MAXNSAPI; n++) {
2398 if (linked_pdp->secondary_tei[n]) {
2399 if (pdp_getgtp1
2400 (&secondary_pdp,
2401 linked_pdp->secondary_tei[n])) {
2402 gtp_err(LOG_ERR, __FILE__, __LINE__,
2403 "Unknown secondary PDP context");
2404 return EOF;
2405 }
2406 if (linked_pdp != secondary_pdp) {
2407 if (gsn->cb_delete_context)
2408 gsn->cb_delete_context
2409 (secondary_pdp);
2410 pdp_freepdp(secondary_pdp);
2411 }
2412 }
2413 }
2414 if (gsn->cb_delete_context)
2415 gsn->cb_delete_context(linked_pdp);
2416 pdp_freepdp(linked_pdp);
2417 } else {
2418 if (gsn->cb_delete_context)
2419 gsn->cb_delete_context(pdp);
2420 if (pdp == linked_pdp) {
2421 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2422 linked_pdp->nodata = 1;
2423 } else
2424 pdp_freepdp(pdp);
2425 }
2426
2427 return 0;
jjako2c381332003-10-21 19:09:53 +00002428}
jjako08d331d2003-10-13 20:33:30 +00002429
jjako52c24142002-12-16 13:33:51 +00002430/* Send Delete PDP Context Response */
2431int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002432 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002433 void *pack, unsigned len,
2434 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002435 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002436{
Harald Weltebed35df2011-11-02 13:06:18 +01002437 union gtp_packet packet;
2438 struct pdp_t *secondary_pdp;
2439 unsigned int length =
2440 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2441 int n;
jjako52c24142002-12-16 13:33:51 +00002442
Harald Weltebed35df2011-11-02 13:06:18 +01002443 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002444
Harald Weltebed35df2011-11-02 13:06:18 +01002445 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2446 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002447
Harald Weltebed35df2011-11-02 13:06:18 +01002448 if (cause == GTPCAUSE_ACC_REQ) {
2449 if ((teardown) || (version == 0)) { /* Remove all contexts */
2450 for (n = 0; n < PDP_MAXNSAPI; n++) {
2451 if (linked_pdp->secondary_tei[n]) {
2452 if (pdp_getgtp1
2453 (&secondary_pdp,
2454 linked_pdp->secondary_tei[n])) {
2455 gtp_err(LOG_ERR, __FILE__,
2456 __LINE__,
2457 "Unknown secondary PDP context");
2458 return EOF;
2459 }
2460 if (linked_pdp != secondary_pdp) {
2461 if (gsn->cb_delete_context)
2462 gsn->cb_delete_context
2463 (secondary_pdp);
2464 pdp_freepdp(secondary_pdp);
2465 }
2466 }
2467 }
2468 if (gsn->cb_delete_context)
2469 gsn->cb_delete_context(linked_pdp);
2470 pdp_freepdp(linked_pdp);
2471 } else { /* Remove only current context */
2472 if (gsn->cb_delete_context)
2473 gsn->cb_delete_context(pdp);
2474 if (pdp == linked_pdp) {
2475 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2476 0;
2477 linked_pdp->nodata = 1;
2478 } else
2479 pdp_freepdp(pdp);
2480 }
jjako2c381332003-10-21 19:09:53 +00002481 }
Harald Weltebed35df2011-11-02 13:06:18 +01002482 /* if (cause == GTPCAUSE_ACC_REQ) */
2483 return 0;
jjako52c24142002-12-16 13:33:51 +00002484}
2485
2486/* Handle Delete PDP Context Request */
2487int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002488 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002489 void *pack, unsigned len)
2490{
2491 struct pdp_t *pdp = NULL;
2492 struct pdp_t *linked_pdp = NULL;
2493 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002494
Harald Weltebed35df2011-11-02 13:06:18 +01002495 uint16_t seq = get_seq(pack);
2496 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002497
Harald Weltebed35df2011-11-02 13:06:18 +01002498 uint8_t nsapi;
2499 uint8_t teardown = 0;
2500 int n;
2501 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002502
Harald Weltebed35df2011-11-02 13:06:18 +01002503 /* Is this a dublicate ? */
2504 if (!gtp_dublicate(gsn, version, peer, seq)) {
2505 return 0; /* We allready send off response once */
2506 }
jjako2c381332003-10-21 19:09:53 +00002507
Harald Weltebed35df2011-11-02 13:06:18 +01002508 /* Find the linked context in question */
2509 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2510 gsn->err_unknownpdp++;
2511 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2512 "Unknown PDP context");
2513 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2514 NULL, NULL, GTPCAUSE_NON_EXIST,
2515 teardown);
2516 }
jjako2c381332003-10-21 19:09:53 +00002517
Harald Weltebed35df2011-11-02 13:06:18 +01002518 /* If version 0 this is also the secondary context */
2519 if (version == 0)
2520 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +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++;
2525 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2526 "Invalid message format");
2527 if (0 == version)
2528 return EOF;
2529 else
2530 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2531 len, NULL, NULL,
2532 GTPCAUSE_INVALID_MESSAGE,
2533 teardown);
2534 }
2535
2536 if (version == 1) {
2537 /* NSAPI (mandatory) */
2538 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2539 gsn->missing++;
2540 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2541 len, "Missing mandatory information field");
2542 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2543 len, NULL, NULL,
2544 GTPCAUSE_MAN_IE_MISSING,
2545 teardown);
2546 }
2547
2548 /* Find the context in question */
2549 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2550 gsn->err_unknownpdp++;
2551 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2552 len, "Unknown PDP context");
2553 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2554 len, NULL, NULL,
2555 GTPCAUSE_NON_EXIST,
2556 teardown);
2557 }
2558
2559 /* Teardown (conditional) */
2560 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2561
2562 if (!teardown) {
2563 for (n = 0; n < PDP_MAXNSAPI; n++)
2564 if (linked_pdp->secondary_tei[n])
2565 count++;
2566 if (count <= 1) {
2567 return 0; /* 29.060 7.3.5 Ignore message */
2568 }
2569 }
2570 }
2571
2572 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2573 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002574}
2575
jjako52c24142002-12-16 13:33:51 +00002576/* Handle Delete PDP Context Response */
2577int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002578 struct sockaddr_in *peer, void *pack, unsigned len)
2579{
2580 union gtpie_member *ie[GTPIE_SIZE];
2581 uint8_t cause;
2582 void *cbp = NULL;
2583 uint8_t type = 0;
2584 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002585
Harald Weltebed35df2011-11-02 13:06:18 +01002586 /* Remove packet from queue */
2587 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2588 return EOF;
jjako52c24142002-12-16 13:33:51 +00002589
Harald Weltebed35df2011-11-02 13:06:18 +01002590 /* Decode information elements */
2591 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2592 gsn->invalid++;
2593 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2594 "Invalid message format");
2595 if (gsn->cb_conf)
2596 gsn->cb_conf(type, EOF, NULL, cbp);
2597 return EOF;
2598 }
2599
2600 /* Extract cause value (mandatory) */
2601 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2602 gsn->missing++;
2603 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2604 "Missing mandatory information field");
2605 if (gsn->cb_conf)
2606 gsn->cb_conf(type, EOF, NULL, cbp);
2607 return EOF;
2608 }
2609
2610 /* Check the cause value (again) */
2611 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2612 gsn->err_cause++;
2613 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2614 "Unexpected cause value received: %d", cause);
2615 if (gsn->cb_conf)
2616 gsn->cb_conf(type, cause, NULL, cbp);
2617 return EOF;
2618 }
2619
2620 /* Callback function to notify application */
2621 if (gsn->cb_conf)
2622 gsn->cb_conf(type, cause, NULL, cbp);
2623
2624 return 0;
jjako52c24142002-12-16 13:33:51 +00002625}
2626
2627/* Send Error Indication (response to a GPDU message */
2628int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002629 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002630 void *pack, unsigned len)
2631{
Harald Weltebed35df2011-11-02 13:06:18 +01002632 union gtp_packet packet;
2633 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2634
2635 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2636 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002637}
2638
2639/* Handle Error Indication */
2640int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002641 struct sockaddr_in *peer, void *pack, unsigned len)
2642{
2643 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002644
Harald Weltebed35df2011-11-02 13:06:18 +01002645 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002646 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002647 gsn->err_unknownpdp++;
2648 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2649 "Unknown PDP context");
2650 return EOF;
2651 }
jjako52c24142002-12-16 13:33:51 +00002652
Harald Weltebed35df2011-11-02 13:06:18 +01002653 gsn->err_unknownpdp++; /* TODO: Change counter */
2654 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2655 "Received Error Indication");
2656
2657 if (gsn->cb_delete_context)
2658 gsn->cb_delete_context(pdp);
2659 pdp_freepdp(pdp);
2660 return 0;
jjako52c24142002-12-16 13:33:51 +00002661}
2662
2663int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002664 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2665{
jjako08d331d2003-10-13 20:33:30 +00002666
Harald Weltebed35df2011-11-02 13:06:18 +01002667 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002668
Harald Weltebed35df2011-11-02 13:06:18 +01002669 /* Need to include code to verify packet src and dest addresses */
2670 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002671
Harald Weltebed35df2011-11-02 13:06:18 +01002672 if (version == 0) {
2673 if (pdp_getgtp0
2674 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2675 gsn->err_unknownpdp++;
2676 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2677 len, "Unknown PDP context");
2678 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2679 len);
2680 }
2681 hlen = GTP0_HEADER_SIZE;
2682 } else if (version == 1) {
2683 if (pdp_getgtp1
2684 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2685 gsn->err_unknownpdp++;
2686 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2687 len, "Unknown PDP context");
2688 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2689 len);
2690 }
jjako08d331d2003-10-13 20:33:30 +00002691
Harald Weltebed35df2011-11-02 13:06:18 +01002692 /* Is this a long or a short header ? */
2693 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2694 hlen = GTP1_HEADER_SIZE_LONG;
2695 else
2696 hlen = GTP1_HEADER_SIZE_SHORT;
2697 } else {
2698 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2699 "Unknown version");
2700 }
jjako08d331d2003-10-13 20:33:30 +00002701
Harald Weltebed35df2011-11-02 13:06:18 +01002702 /* If the GPDU was not from the peer GSN tell him to delete context */
2703 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2704 gsn->err_unknownpdp++;
2705 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2706 "Unknown PDP context");
2707 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2708 }
jjako52c24142002-12-16 13:33:51 +00002709
Harald Weltebed35df2011-11-02 13:06:18 +01002710 /* Callback function */
2711 if (gsn->cb_data_ind != 0)
2712 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2713
2714 return 0;
jjako52c24142002-12-16 13:33:51 +00002715}
2716
jjako52c24142002-12-16 13:33:51 +00002717/* Receives GTP packet and sends off for further processing
2718 * Function will check the validity of the header. If the header
2719 * is not valid the packet is either dropped or a version not
2720 * supported is returned to the peer.
2721 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002722int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002723{
Harald Weltebed35df2011-11-02 13:06:18 +01002724 unsigned char buffer[PACKET_MAX];
2725 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002726 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002727 int status;
2728 struct gtp0_header *pheader;
2729 int version = 0; /* GTP version should be determined from header! */
2730 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002731
Harald Weltebed35df2011-11-02 13:06:18 +01002732 /* TODO: Need strategy of userspace buffering and blocking */
2733 /* Currently read is non-blocking and send is blocking. */
2734 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002735
Harald Weltebed35df2011-11-02 13:06:18 +01002736 while (1) { /* Loop until no more to read */
2737 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
2738 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2739 return -1;
2740 }
2741 peerlen = sizeof(peer);
2742 if ((status =
2743 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2744 (struct sockaddr *)&peer, &peerlen)) < 0) {
2745 if (errno == EAGAIN)
2746 return 0;
2747 gsn->err_readfrom++;
2748 gtp_err(LOG_ERR, __FILE__, __LINE__,
2749 "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
2750 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2751 status, status ? strerror(errno) : "No error");
2752 return -1;
2753 }
jjako1db1c812003-07-06 20:53:57 +00002754
Harald Weltebed35df2011-11-02 13:06:18 +01002755 /* Need at least 1 byte in order to check version */
2756 if (status < (1)) {
2757 gsn->empty++;
2758 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2759 status, "Discarding packet - too small");
2760 continue;
2761 }
jjako08d331d2003-10-13 20:33:30 +00002762
Harald Weltebed35df2011-11-02 13:06:18 +01002763 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002764
Harald Weltebed35df2011-11-02 13:06:18 +01002765 /* Version should be gtp0 (or earlier) */
2766 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2767 /* GTP 0 messages. If other version message is received we reply that we */
2768 /* only support version 0, implying that this is the only version */
2769 /* supported on this port */
2770 if (((pheader->flags & 0xe0) > 0x00)) {
2771 gsn->unsup++;
2772 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2773 status, "Unsupported GTP version");
2774 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2775 continue;
2776 }
2777
2778 /* Check length of gtp0 packet */
2779 if (status < GTP0_HEADER_SIZE) {
2780 gsn->tooshort++;
2781 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2782 status, "GTP0 packet too short");
2783 continue; /* Silently discard 29.60: 11.1.2 */
2784 }
2785
2786 /* Check packet length field versus length of packet */
2787 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2788 gsn->tooshort++;
2789 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2790 status,
2791 "GTP packet length field does not match actual length");
2792 continue; /* Silently discard */
2793 }
2794
2795 if ((gsn->mode == GTP_MODE_GGSN) &&
2796 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2797 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2798 (pheader->type == GTP_DELETE_PDP_RSP))) {
2799 gsn->unexpect++;
2800 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2801 status,
2802 "Unexpected GTP Signalling Message");
2803 continue; /* Silently discard 29.60: 11.1.4 */
2804 }
2805
2806 if ((gsn->mode == GTP_MODE_SGSN) &&
2807 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2808 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2809 (pheader->type == GTP_DELETE_PDP_REQ))) {
2810 gsn->unexpect++;
2811 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2812 status,
2813 "Unexpected GTP Signalling Message");
2814 continue; /* Silently discard 29.60: 11.1.4 */
2815 }
2816
2817 switch (pheader->type) {
2818 case GTP_ECHO_REQ:
2819 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2820 break;
2821 case GTP_ECHO_RSP:
2822 gtp_echo_conf(gsn, version, &peer, buffer, status);
2823 break;
2824 case GTP_NOT_SUPPORTED:
2825 gtp_unsup_ind(gsn, &peer, buffer, status);
2826 break;
2827 case GTP_CREATE_PDP_REQ:
2828 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2829 status);
2830 break;
2831 case GTP_CREATE_PDP_RSP:
2832 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2833 status);
2834 break;
2835 case GTP_UPDATE_PDP_REQ:
2836 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2837 status);
2838 break;
2839 case GTP_UPDATE_PDP_RSP:
2840 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2841 status);
2842 break;
2843 case GTP_DELETE_PDP_REQ:
2844 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2845 status);
2846 break;
2847 case GTP_DELETE_PDP_RSP:
2848 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2849 status);
2850 break;
2851 case GTP_ERROR:
2852 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2853 break;
2854 case GTP_GPDU:
2855 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2856 break;
2857 default:
2858 gsn->unknown++;
2859 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2860 status,
2861 "Unknown GTP message type received");
2862 break;
2863 }
2864 }
jjako08d331d2003-10-13 20:33:30 +00002865}
2866
jjako08d331d2003-10-13 20:33:30 +00002867int gtp_decaps1c(struct gsn_t *gsn)
2868{
Harald Weltebed35df2011-11-02 13:06:18 +01002869 unsigned char buffer[PACKET_MAX];
2870 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002871 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002872 int status;
2873 struct gtp1_header_short *pheader;
2874 int version = 1; /* TODO GTP version should be determined from header! */
2875 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002876
Harald Weltebed35df2011-11-02 13:06:18 +01002877 /* TODO: Need strategy of userspace buffering and blocking */
2878 /* Currently read is non-blocking and send is blocking. */
2879 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002880
Harald Weltebed35df2011-11-02 13:06:18 +01002881 while (1) { /* Loop until no more to read */
2882 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
2883 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2884 return -1;
2885 }
2886 peerlen = sizeof(peer);
2887 if ((status =
2888 recvfrom(fd, buffer, sizeof(buffer), 0,
2889 (struct sockaddr *)&peer, &peerlen)) < 0) {
2890 if (errno == EAGAIN)
2891 return 0;
2892 gsn->err_readfrom++;
2893 gtp_err(LOG_ERR, __FILE__, __LINE__,
2894 "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
2895 fd, (unsigned long)buffer, sizeof(buffer),
2896 status, status ? strerror(errno) : "No error");
2897 return -1;
2898 }
jjako08d331d2003-10-13 20:33:30 +00002899
Harald Weltebed35df2011-11-02 13:06:18 +01002900 /* Need at least 1 byte in order to check version */
2901 if (status < (1)) {
2902 gsn->empty++;
2903 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2904 status, "Discarding packet - too small");
2905 continue;
2906 }
jjako08d331d2003-10-13 20:33:30 +00002907
Harald Weltebed35df2011-11-02 13:06:18 +01002908 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002909
Harald Weltebed35df2011-11-02 13:06:18 +01002910 /* Version must be no larger than GTP 1 */
2911 if (((pheader->flags & 0xe0) > 0x20)) {
2912 gsn->unsup++;
2913 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2914 status, "Unsupported GTP version");
2915 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2916 /*29.60: 11.1.1 */
2917 continue;
2918 }
jjako08d331d2003-10-13 20:33:30 +00002919
Harald Weltebed35df2011-11-02 13:06:18 +01002920 /* Version must be at least GTP 1 */
2921 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2922 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2923 /* the message */
2924 if (((pheader->flags & 0xe0) < 0x20)) {
2925 gsn->unsup++;
2926 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2927 status, "Unsupported GTP version");
2928 continue;
2929 }
jjako08d331d2003-10-13 20:33:30 +00002930
Harald Weltebed35df2011-11-02 13:06:18 +01002931 /* Check packet flag field */
2932 if (((pheader->flags & 0xf7) != 0x32)) {
2933 gsn->unsup++;
2934 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2935 status, "Unsupported packet flag");
2936 continue;
2937 }
jjako2c381332003-10-21 19:09:53 +00002938
Harald Weltebed35df2011-11-02 13:06:18 +01002939 /* Check length of packet */
2940 if (status < GTP1_HEADER_SIZE_LONG) {
2941 gsn->tooshort++;
2942 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2943 status, "GTP packet too short");
2944 continue; /* Silently discard 29.60: 11.1.2 */
2945 }
jjako2c381332003-10-21 19:09:53 +00002946
Harald Weltebed35df2011-11-02 13:06:18 +01002947 /* Check packet length field versus length of packet */
2948 if (status !=
2949 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2950 gsn->tooshort++;
2951 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2952 status,
2953 "GTP packet length field does not match actual length");
2954 continue; /* Silently discard */
2955 }
jjako1db1c812003-07-06 20:53:57 +00002956
Harald Weltebed35df2011-11-02 13:06:18 +01002957 /* Check for extension headers */
2958 /* TODO: We really should cycle through the headers and determine */
2959 /* if any have the comprehension required flag set */
2960 if (((pheader->flags & 0x04) != 0x00)) {
2961 gsn->unsup++;
2962 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2963 status, "Unsupported extension header");
2964 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2965 status);
jjako1db1c812003-07-06 20:53:57 +00002966
Harald Weltebed35df2011-11-02 13:06:18 +01002967 continue;
2968 }
2969
2970 if ((gsn->mode == GTP_MODE_GGSN) &&
2971 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2972 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2973 (pheader->type == GTP_DELETE_PDP_RSP))) {
2974 gsn->unexpect++;
2975 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2976 status,
2977 "Unexpected GTP Signalling Message");
2978 continue; /* Silently discard 29.60: 11.1.4 */
2979 }
2980
2981 if ((gsn->mode == GTP_MODE_SGSN) &&
2982 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2983 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2984 (pheader->type == GTP_DELETE_PDP_REQ))) {
2985 gsn->unexpect++;
2986 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2987 status,
2988 "Unexpected GTP Signalling Message");
2989 continue; /* Silently discard 29.60: 11.1.4 */
2990 }
2991
2992 switch (pheader->type) {
2993 case GTP_ECHO_REQ:
2994 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2995 break;
2996 case GTP_ECHO_RSP:
2997 gtp_echo_conf(gsn, version, &peer, buffer, status);
2998 break;
2999 case GTP_NOT_SUPPORTED:
3000 gtp_unsup_ind(gsn, &peer, buffer, status);
3001 break;
3002 case GTP_SUPP_EXT_HEADER:
3003 gtp_extheader_ind(gsn, &peer, buffer, status);
3004 break;
3005 case GTP_CREATE_PDP_REQ:
3006 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3007 status);
3008 break;
3009 case GTP_CREATE_PDP_RSP:
3010 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3011 status);
3012 break;
3013 case GTP_UPDATE_PDP_REQ:
3014 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3015 status);
3016 break;
3017 case GTP_UPDATE_PDP_RSP:
3018 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3019 status);
3020 break;
3021 case GTP_DELETE_PDP_REQ:
3022 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3023 status);
3024 break;
3025 case GTP_DELETE_PDP_RSP:
3026 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3027 status);
3028 break;
3029 case GTP_ERROR:
3030 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3031 break;
3032 default:
3033 gsn->unknown++;
3034 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3035 status,
3036 "Unknown GTP message type received");
3037 break;
3038 }
3039 }
jjako52c24142002-12-16 13:33:51 +00003040}
3041
jjako08d331d2003-10-13 20:33:30 +00003042int gtp_decaps1u(struct gsn_t *gsn)
3043{
Harald Weltebed35df2011-11-02 13:06:18 +01003044 unsigned char buffer[PACKET_MAX];
3045 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003046 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003047 int status;
3048 struct gtp1_header_short *pheader;
3049 int version = 1; /* GTP version should be determined from header! */
3050 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003051
Harald Weltebed35df2011-11-02 13:06:18 +01003052 /* TODO: Need strategy of userspace buffering and blocking */
3053 /* Currently read is non-blocking and send is blocking. */
3054 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003055
Harald Weltebed35df2011-11-02 13:06:18 +01003056 while (1) { /* Loop until no more to read */
3057 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
3058 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3059 return -1;
3060 }
3061 peerlen = sizeof(peer);
3062 if ((status =
3063 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3064 (struct sockaddr *)&peer, &peerlen)) < 0) {
3065 if (errno == EAGAIN)
3066 return 0;
3067 gsn->err_readfrom++;
3068 gtp_err(LOG_ERR, __FILE__, __LINE__,
3069 "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
3070 gsn->fd1u, (unsigned long)buffer,
3071 sizeof(buffer), status,
3072 status ? strerror(errno) : "No error");
3073 return -1;
3074 }
jjako08d331d2003-10-13 20:33:30 +00003075
Harald Weltebed35df2011-11-02 13:06:18 +01003076 /* Need at least 1 byte in order to check version */
3077 if (status < (1)) {
3078 gsn->empty++;
3079 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3080 status, "Discarding packet - too small");
3081 continue;
3082 }
jjako08d331d2003-10-13 20:33:30 +00003083
Harald Weltebed35df2011-11-02 13:06:18 +01003084 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003085
Harald Weltebed35df2011-11-02 13:06:18 +01003086 /* Version must be no larger than GTP 1 */
3087 if (((pheader->flags & 0xe0) > 0x20)) {
3088 gsn->unsup++;
3089 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3090 status, "Unsupported GTP version");
3091 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3092 continue;
3093 }
jjako08d331d2003-10-13 20:33:30 +00003094
Harald Weltebed35df2011-11-02 13:06:18 +01003095 /* Version must be at least GTP 1 */
3096 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3097 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3098 /* the message */
3099 if (((pheader->flags & 0xe0) < 0x20)) {
3100 gsn->unsup++;
3101 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3102 status, "Unsupported GTP version");
3103 continue;
3104 }
jjako2c381332003-10-21 19:09:53 +00003105
Harald Weltebed35df2011-11-02 13:06:18 +01003106 /* Check packet flag field (allow both with and without sequence number) */
3107 if (((pheader->flags & 0xf5) != 0x30)) {
3108 gsn->unsup++;
3109 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3110 status, "Unsupported packet flag");
3111 continue;
3112 }
jjako2c381332003-10-21 19:09:53 +00003113
Harald Weltebed35df2011-11-02 13:06:18 +01003114 /* Check length of packet */
3115 if (status < GTP1_HEADER_SIZE_SHORT) {
3116 gsn->tooshort++;
3117 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3118 status, "GTP packet too short");
3119 continue; /* Silently discard 29.60: 11.1.2 */
3120 }
3121
3122 /* Check packet length field versus length of packet */
3123 if (status !=
3124 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3125 gsn->tooshort++;
3126 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3127 status,
3128 "GTP packet length field does not match actual length");
3129 continue; /* Silently discard */
3130 }
3131
3132 /* Check for extension headers */
3133 /* TODO: We really should cycle through the headers and determine */
3134 /* if any have the comprehension required flag set */
3135 if (((pheader->flags & 0x04) != 0x00)) {
3136 gsn->unsup++;
3137 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3138 status, "Unsupported extension header");
3139 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3140 status);
3141
3142 continue;
3143 }
3144
3145 switch (pheader->type) {
3146 case GTP_ECHO_REQ:
3147 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3148 break;
3149 case GTP_ECHO_RSP:
3150 gtp_echo_conf(gsn, version, &peer, buffer, status);
3151 break;
3152 case GTP_SUPP_EXT_HEADER:
3153 gtp_extheader_ind(gsn, &peer, buffer, status);
3154 break;
3155 case GTP_ERROR:
3156 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3157 break;
3158 /* Supported header extensions */
3159 case GTP_GPDU:
3160 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3161 break;
3162 default:
3163 gsn->unknown++;
3164 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3165 status,
3166 "Unknown GTP message type received");
3167 break;
3168 }
3169 }
jjako08d331d2003-10-13 20:33:30 +00003170}
3171
Harald Weltebed35df2011-11-02 13:06:18 +01003172int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003173{
Harald Weltebed35df2011-11-02 13:06:18 +01003174 union gtp_packet packet;
3175 struct sockaddr_in addr;
3176 int fd;
3177 int length;
jjako52c24142002-12-16 13:33:51 +00003178
Harald Weltebed35df2011-11-02 13:06:18 +01003179 memset(&addr, 0, sizeof(addr));
3180 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003181#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003182 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003183#endif
3184
Harald Weltebed35df2011-11-02 13:06:18 +01003185 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003186
Harald Weltebed35df2011-11-02 13:06:18 +01003187 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003188
Harald Weltebed35df2011-11-02 13:06:18 +01003189 length = GTP0_HEADER_SIZE + len;
3190 addr.sin_port = htons(GTP0_PORT);
3191 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003192
Harald Weltebed35df2011-11-02 13:06:18 +01003193 get_default_gtp(0, GTP_GPDU, &packet);
3194 packet.gtp0.h.length = hton16(len);
3195 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3196 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003197 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003198
Harald Weltebed35df2011-11-02 13:06:18 +01003199 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3200 gsn->err_memcpy++;
3201 gtp_err(LOG_ERR, __FILE__, __LINE__,
3202 "Memcpy failed: %d > %d", len,
3203 sizeof(union gtp_packet) -
3204 sizeof(struct gtp0_header));
3205 return EOF;
3206 }
3207 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3208 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003209
Harald Weltebed35df2011-11-02 13:06:18 +01003210 length = GTP1_HEADER_SIZE_LONG + len;
3211 addr.sin_port = htons(GTP1U_PORT);
3212 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003213
Harald Weltebed35df2011-11-02 13:06:18 +01003214 get_default_gtp(1, GTP_GPDU, &packet);
3215 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3216 GTP1_HEADER_SIZE_LONG);
3217 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3218 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3219
3220 if (len >
3221 sizeof(union gtp_packet) -
3222 sizeof(struct gtp1_header_long)) {
3223 gsn->err_memcpy++;
3224 gtp_err(LOG_ERR, __FILE__, __LINE__,
3225 "Memcpy failed: %d > %d", len,
3226 sizeof(union gtp_packet) -
3227 sizeof(struct gtp0_header));
3228 return EOF;
3229 }
3230 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3231 } else {
3232 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
3233 return EOF;
3234 }
3235
3236 if (fcntl(fd, F_SETFL, 0)) {
3237 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3238 return -1;
3239 }
3240
3241 if (sendto(fd, &packet, length, 0,
3242 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3243 gsn->err_sendto++;
3244 gtp_err(LOG_ERR, __FILE__, __LINE__,
3245 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
3246 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3247 strerror(errno));
3248 return EOF;
3249 }
3250 return 0;
jjako52c24142002-12-16 13:33:51 +00003251}
3252
jjako52c24142002-12-16 13:33:51 +00003253/* ***********************************************************
3254 * Conversion functions
3255 *************************************************************/
3256
Harald Weltebed35df2011-11-02 13:06:18 +01003257int char2ul_t(char *src, struct ul_t dst)
3258{
3259 dst.l = strlen(src) + 1;
3260 dst.v = malloc(dst.l);
3261 dst.v[0] = dst.l - 1;
3262 memcpy(&dst.v[1], src, dst.v[0]);
3263 return 0;
jjako52c24142002-12-16 13:33:51 +00003264}
3265
3266/* ***********************************************************
3267 * IP address conversion functions
3268 * There exist several types of address representations:
3269 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3270 * Used for signalling address to mobile station. Supports IPv4
3271 * IPv6 x.25 etc. etc.
3272 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3273 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3274 * - in_addr: IPv4 address struct.
3275 * - sockaddr_in: Socket API representation of IP address and
3276 * port number.
3277 *************************************************************/
3278
Harald Weltebed35df2011-11-02 13:06:18 +01003279int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3280{
3281 eua->v[0] = 0xf1; /* IETF */
3282 eua->v[1] = 0x21; /* IPv4 */
3283 if (src) {
3284 eua->l = 6;
3285 memcpy(&eua->v[2], src, 4);
3286 } else {
3287 eua->l = 2;
3288 }
3289 return 0;
jjako52c24142002-12-16 13:33:51 +00003290}
3291
Harald Weltebed35df2011-11-02 13:06:18 +01003292int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3293{
3294 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3295 return -1; /* Not IPv4 address */
3296 memcpy(dst, &eua->v[2], 4);
3297 return 0;
jjako52c24142002-12-16 13:33:51 +00003298}
3299
Harald Weltebed35df2011-11-02 13:06:18 +01003300int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3301{
3302 memset(dst, 0, sizeof(struct in_addr));
3303 if (gsna->l != 4)
3304 return EOF; /* Return if not IPv4 */
3305 memcpy(dst, gsna->v, gsna->l);
3306 return 0;
jjako52c24142002-12-16 13:33:51 +00003307}
3308
Harald Weltebed35df2011-11-02 13:06:18 +01003309int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3310{
3311 memset(gsna, 0, sizeof(struct ul16_t));
3312 gsna->l = 4;
3313 memcpy(gsna->v, src, gsna->l);
3314 return 0;
jjako52c24142002-12-16 13:33:51 +00003315}