blob: fd4f0d093b9a94c55d2e6c2f78c906745358ab6e [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
jjako0fe0df02004-09-17 11:30:40 +000024#include "../config.h"
25#ifdef HAVE_STDINT_H
26#include <stdint.h>
27#endif
jjako52c24142002-12-16 13:33:51 +000028
29#include <syslog.h>
30#include <stdio.h>
31#include <stdarg.h>
32#include <stdlib.h>
33#include <sys/time.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <sys/stat.h>
39#include <time.h>
40#include <unistd.h>
41#include <string.h>
42#include <errno.h>
43#include <fcntl.h>
44
45#include <arpa/inet.h>
46
jjakobae2cd42004-01-09 12:04:39 +000047/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000048
49#include "pdp.h"
50#include "gtp.h"
51#include "gtpie.h"
52#include "queue.h"
53
Harald Welte95848ba2011-11-02 18:17:50 +010054/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
55#define N3_REQUESTS 5
56
57#define T3_REQUEST 3
58
jjako1db1c812003-07-06 20:53:57 +000059/* Error reporting functions */
60
Harald Weltebed35df2011-11-02 13:06:18 +010061void gtp_err(int priority, char *filename, int linenum, char *fmt, ...)
62{
63 va_list args;
64 char buf[ERRMSG_SIZE];
jjako1db1c812003-07-06 20:53:57 +000065
Harald Weltebed35df2011-11-02 13:06:18 +010066 va_start(args, fmt);
67 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
68 va_end(args);
69 buf[ERRMSG_SIZE - 1] = 0;
70 syslog(priority, "%s: %d: %s", filename, linenum, buf);
jjako1db1c812003-07-06 20:53:57 +000071}
72
73void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +010074 void *pack, unsigned len, char *fmt, ...)
75{
jjako1db1c812003-07-06 20:53:57 +000076
Harald Weltebed35df2011-11-02 13:06:18 +010077 va_list args;
78 char buf[ERRMSG_SIZE];
79 char buf2[ERRMSG_SIZE];
80 unsigned int n;
81 int pos;
82
83 va_start(args, fmt);
84 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
85 va_end(args);
86 buf[ERRMSG_SIZE - 1] = 0;
87
88 snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
89 inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
90 buf2[ERRMSG_SIZE - 1] = 0;
91 pos = strlen(buf2);
92 for (n = 0; n < len; n++) {
93 if ((pos + 4) < ERRMSG_SIZE) {
94 sprintf((buf2 + pos), " %02hhx",
95 ((unsigned char *)pack)[n]);
96 pos += 3;
97 }
98 }
99 buf2[pos] = 0;
100
101 syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
jjako1db1c812003-07-06 20:53:57 +0000102
103}
104
jjako52c24142002-12-16 13:33:51 +0000105/* API Functions */
106
Harald Weltebed35df2011-11-02 13:06:18 +0100107const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +0000108{
Harald Weltebed35df2011-11-02 13:06:18 +0100109 return VERSION;
jjako52c24142002-12-16 13:33:51 +0000110}
111
112/* gtp_new */
113/* gtp_free */
114
Harald Weltebed35df2011-11-02 13:06:18 +0100115int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
116 uint64_t imsi, uint8_t nsapi)
117{
118 return pdp_newpdp(pdp, imsi, nsapi, NULL);
jjako52c24142002-12-16 13:33:51 +0000119}
120
Harald Weltebed35df2011-11-02 13:06:18 +0100121int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
122{
123 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000124}
125
jjako52c24142002-12-16 13:33:51 +0000126/* gtp_gpdu */
127
Harald Weltebed35df2011-11-02 13:06:18 +0100128extern int gtp_fd(struct gsn_t *gsn)
129{
130 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000131}
132
133/* gtp_decaps */
134/* gtp_retrans */
135/* gtp_retranstimeout */
136
jjako08d331d2003-10-13 20:33:30 +0000137int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100138 int (*cb) (struct sockaddr_in * peer))
139{
140 gsn->cb_unsup_ind = cb;
141 return 0;
jjako08d331d2003-10-13 20:33:30 +0000142}
143
jjako2c381332003-10-21 19:09:53 +0000144int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100145 int (*cb) (struct sockaddr_in * peer))
146{
147 gsn->cb_extheader_ind = cb;
148 return 0;
jjako2c381332003-10-21 19:09:53 +0000149}
150
jjako08d331d2003-10-13 20:33:30 +0000151/* API: Initialise delete context callback */
152/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100153int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000154{
Harald Weltebed35df2011-11-02 13:06:18 +0100155 gsn->cb_delete_context = cb;
156 return 0;
jjako52c24142002-12-16 13:33:51 +0000157}
158
jjako52c24142002-12-16 13:33:51 +0000159int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100160 int (*cb) (int type, int cause,
161 struct pdp_t * pdp, void *cbp))
162{
163 gsn->cb_conf = cb;
164 return 0;
jjako52c24142002-12-16 13:33:51 +0000165}
166
Harald Welte629e9862010-12-24 20:58:09 +0100167int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100168 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
169{
170 gsn->cb_recovery = cb;
171 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100172}
173
jjako08d331d2003-10-13 20:33:30 +0000174extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100175 int (*cb_data_ind) (struct pdp_t * pdp,
176 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000177{
Harald Weltebed35df2011-11-02 13:06:18 +0100178 gsn->cb_data_ind = cb_data_ind;
179 return 0;
jjako52c24142002-12-16 13:33:51 +0000180}
181
jjako08d331d2003-10-13 20:33:30 +0000182/**
183 * get_default_gtp()
184 * Generate a GPRS Tunneling Protocol signalling packet header, depending
185 * on GTP version and message type. pdp is used for teid/flow label.
186 * *packet must be allocated by the calling function, and be large enough
187 * to hold the packet header.
188 * returns the length of the header. 0 on error.
189 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100190static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
191{
192 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
193 struct gtp1_header_long *gtp1_default =
194 (struct gtp1_header_long *)packet;
195 switch (version) {
196 case 0:
197 /* Initialise "standard" GTP0 header */
198 memset(gtp0_default, 0, sizeof(struct gtp0_header));
199 gtp0_default->flags = 0x1e;
200 gtp0_default->type = hton8(type);
201 gtp0_default->spare1 = 0xff;
202 gtp0_default->spare2 = 0xff;
203 gtp0_default->spare3 = 0xff;
204 gtp0_default->number = 0xff;
205 return GTP0_HEADER_SIZE;
206 case 1:
207 /* Initialise "standard" GTP1 header */
208 /* 29.060: 8.2: S=1 and PN=0 */
209 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
210 /* and Supported Extension Headers Notification, the S field shall be */
211 /* set to 1 */
212 /* Currently extension headers are not supported */
213 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
214 gtp1_default->flags = 0x32; /* No extension, enable sequence, no N-PDU */
215 gtp1_default->type = hton8(type);
216 return GTP1_HEADER_SIZE_LONG;
217 default:
218 gtp_err(LOG_ERR, __FILE__, __LINE__,
219 "Unknown GTP packet version");
220 return 0;
221 }
jjako52c24142002-12-16 13:33:51 +0000222}
223
jjako08d331d2003-10-13 20:33:30 +0000224/**
225 * get_seq()
226 * Get sequence number of a packet.
227 * Returns 0 on error
228 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100229static uint16_t get_seq(void *pack)
230{
231 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000232
Harald Weltebed35df2011-11-02 13:06:18 +0100233 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
234 return ntoh16(packet->gtp0.h.seq);
235 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
236 return ntoh16(packet->gtp1l.h.seq);
237 } else {
238 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
239 return 0;
240 }
jjako08d331d2003-10-13 20:33:30 +0000241}
242
243/**
244 * get_tid()
245 * Get tunnel identifier of a packet.
246 * Returns 0 on error
247 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100248static uint64_t get_tid(void *pack)
249{
250 union gtp_packet *packet = (union gtp_packet *)pack;
251
252 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100253 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100254 }
255 return 0;
jjako08d331d2003-10-13 20:33:30 +0000256}
257
258/**
259 * get_hlen()
260 * Get the header length of a packet.
261 * Returns 0 on error
262 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100263static uint16_t get_hlen(void *pack)
264{
265 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000266
Harald Weltebed35df2011-11-02 13:06:18 +0100267 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
268 return GTP0_HEADER_SIZE;
269 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
270 return GTP1_HEADER_SIZE_LONG;
271 } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
272 return GTP1_HEADER_SIZE_SHORT;
273 } else {
274 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
275 return 0;
276 }
jjako08d331d2003-10-13 20:33:30 +0000277}
278
279/**
280 * get_tei()
281 * Get the tunnel endpoint identifier (flow label) of a packet.
282 * Returns 0xffffffff on error.
283 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100284static uint32_t get_tei(void *pack)
285{
286 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000287
Harald Weltebed35df2011-11-02 13:06:18 +0100288 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
289 return ntoh16(packet->gtp0.h.flow);
290 } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
291 return ntoh32(packet->gtp1l.h.tei);
292 } else {
293 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
294 return 0xffffffff;
295 }
jjako08d331d2003-10-13 20:33:30 +0000296}
jjakoa7cd2492003-04-11 09:40:12 +0000297
jjako52c24142002-12-16 13:33:51 +0000298int print_packet(void *packet, unsigned len)
299{
Harald Weltebed35df2011-11-02 13:06:18 +0100300 unsigned int i;
301 printf("The packet looks like this (%d bytes):\n", len);
302 for (i = 0; i < len; i++) {
303 printf("%02x ", (unsigned char)*(char *)(packet + i));
304 if (!((i + 1) % 16))
305 printf("\n");
306 };
307 printf("\n");
308 return 0;
jjako52c24142002-12-16 13:33:51 +0000309}
310
Harald Weltebed35df2011-11-02 13:06:18 +0100311char *snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
312 void *pack, unsigned len, char *buf, int size)
313{
314 unsigned int n;
315 int pos;
316 snprintf(buf, size, "Packet from %s:%u, length: %d, content:",
317 inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
318 buf[size - 1] = 0;
319 pos = strlen(buf);
320 for (n = 0; n < len; n++) {
321 if ((pos + 4) < size) {
322 sprintf((buf + pos), " %02hhx",
323 ((unsigned char *)pack)[n]);
324 pos += 3;
325 }
326 }
327 buf[pos] = 0;
328 return buf;
jjako52c24142002-12-16 13:33:51 +0000329}
330
jjako52c24142002-12-16 13:33:51 +0000331/* ***********************************************************
332 * Reliable delivery of signalling messages
333 *
334 * Sequence numbers are used for both signalling messages and
335 * data messages.
336 *
337 * For data messages each tunnel maintains a sequence counter,
338 * which is incremented by one each time a new data message
339 * is sent. The sequence number starts at (0) zero at tunnel
340 * establishment, and wraps around at 65535 (29.060 9.3.1.1
341 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
342 * or can be used to check the validity of the message in the
343 * receiver, or for reordering af packets.
344 *
345 * For signalling messages the sequence number is used by
346 * signalling messages for which a response is defined. A response
347 * message should copy the sequence from the corresponding request
348 * message. The sequence number "unambiguously" identifies a request
349 * message within a given path, with a path being defined as a set of
350 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
351 * messages shall be responded to, and all response messages associated
352 * with a certain request shall always include the same information"
353 *
354 * We take this to mean that the GSN transmitting a request is free to
355 * choose the sequence number, as long as it is unique within a given path.
356 * It means that we are allowed to count backwards, or roll over at 17
357 * if we prefer that. It also means that we can use the same counter for
358 * all paths. This has the advantage that the transmitted request sequence
359 * numbers are unique within each GSN, and also we dont have to mess around
360 * with path setup and teardown.
361 *
362 * If a response message is lost, the request will be retransmitted, and
363 * the receiving GSN will receive a "duplicated" request. The standard
364 * requires the receiving GSN to send a response, with the same information
365 * as in the original response. For most messages this happens automatically:
366 *
367 * Echo: Automatically dublicates the original response
368 * Create pdp context: The SGSN may send create context request even if
369 * a context allready exist (imsi+nsapi?). This means that the reply will
370 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000371 * side effects in the application which is asked twice to validate
372 * the login.
jjako52c24142002-12-16 13:33:51 +0000373 * Update pdp context: Automatically dublicates the original response???
374 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
375 * a nonexist reply message.
376 *
377 * The correct solution will be to make a queue containing response messages.
378 * This queue should be checked whenever a request is received. If the
379 * response is allready in the queue that response should be transmitted.
380 * It should be possible to find messages in this queue on the basis of
381 * the sequence number and peer GSN IP address (The sequense number is unique
382 * within each path). This need to be implemented by a hash table. Furthermore
383 * it should be possibly to delete messages based on a timeout. This can be
384 * achieved by means of a linked list. The timeout value need to be larger
385 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
386 * set in the peer GSN, so there is no way to know these parameters. On the
387 * other hand the timeout value need to be so small that we do not receive
388 * wraparound sequence numbere before the message is deleted. 60 seconds is
389 * probably not a bad choise.
390 *
391 * This queue however is first really needed from gtp1.
392 *
393 * gtp_req:
394 * Send off a signalling message with appropiate sequence
395 * number. Store packet in queue.
396 * gtp_conf:
397 * Remove an incoming confirmation from the queue
398 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000399 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000400 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000401 * gtp_notification:
402 * Send off a notification message. This is neither a request nor
403 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000404 * gtp_retrans:
405 * Retransmit any outstanding packets which have exceeded
406 * a predefined timeout.
407 *************************************************************/
408
jjako08d331d2003-10-13 20:33:30 +0000409int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100410 union gtp_packet *packet, int len,
411 struct in_addr *inetaddr, void *cbp)
412{
413 struct sockaddr_in addr;
414 struct qmsg_t *qmsg;
415 int fd;
jjako08d331d2003-10-13 20:33:30 +0000416
Harald Weltebed35df2011-11-02 13:06:18 +0100417 memset(&addr, 0, sizeof(addr));
418 addr.sin_family = AF_INET;
419 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000420#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100421 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000422#endif
jjako52c24142002-12-16 13:33:51 +0000423
Harald Weltebed35df2011-11-02 13:06:18 +0100424 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
425 addr.sin_port = htons(GTP0_PORT);
426 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
427 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100428 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100429 packet->gtp0.h.tid =
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100430 htobe64((pdp->imsi & 0x0fffffffffffffffull) +
431 ((uint64_t) pdp->nsapi << 60));
432 }
Harald Weltebed35df2011-11-02 13:06:18 +0100433 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
434 || (packet->gtp0.h.type == GTP_ERROR)))
435 packet->gtp0.h.flow = hton16(pdp->flru);
436 else if (pdp)
437 packet->gtp0.h.flow = hton16(pdp->flrc);
438 fd = gsn->fd0;
439 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
440 addr.sin_port = htons(GTP1C_PORT);
441 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
442 packet->gtp1l.h.seq = hton16(gsn->seq_next);
443 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
444 (packet->gtp1l.h.type == GTP_ERROR)))
445 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
446 else if (pdp)
447 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
448 fd = gsn->fd1c;
449 } else {
450 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
451 return -1;
452 }
jjako52c24142002-12-16 13:33:51 +0000453
Harald Weltebed35df2011-11-02 13:06:18 +0100454 if (sendto(fd, packet, len, 0,
455 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
456 gsn->err_sendto++;
457 gtp_err(LOG_ERR, __FILE__, __LINE__,
458 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
459 (unsigned long)&packet, len, strerror(errno));
460 return -1;
461 }
462
463 /* Use new queue structure */
464 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
465 gsn->err_queuefull++;
466 gtp_err(LOG_ERR, __FILE__, __LINE__,
467 "Retransmit queue is full");
468 } else {
469 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
470 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100471 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100472 qmsg->retrans = 0; /* No retransmissions so far */
473 qmsg->cbp = cbp;
474 qmsg->type = ntoh8(packet->gtp0.h.type);
475 qmsg->fd = fd;
476 }
477 gsn->seq_next++; /* Count up this time */
478 return 0;
jjako52c24142002-12-16 13:33:51 +0000479}
480
481/* gtp_conf
482 * Remove signalling packet from retransmission queue.
483 * return 0 on success, EOF if packet was not found */
484
485int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100486 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
487{
jjako52c24142002-12-16 13:33:51 +0000488
Harald Weltebed35df2011-11-02 13:06:18 +0100489 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000490
Harald Weltebed35df2011-11-02 13:06:18 +0100491 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
492 seq = ntoh16(packet->gtp0.h.seq);
493 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
494 seq = ntoh16(packet->gtp1l.h.seq);
495 else {
496 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
497 "Unknown GTP packet version");
498 return EOF;
499 }
jjako08d331d2003-10-13 20:33:30 +0000500
Harald Weltebed35df2011-11-02 13:06:18 +0100501 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
502 gsn->err_seq++;
503 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
504 "Confirmation packet not found in queue");
505 return EOF;
506 }
jjako52c24142002-12-16 13:33:51 +0000507
Harald Weltebed35df2011-11-02 13:06:18 +0100508 return 0;
jjako52c24142002-12-16 13:33:51 +0000509}
510
Harald Weltebed35df2011-11-02 13:06:18 +0100511int gtp_retrans(struct gsn_t *gsn)
512{
513 /* Retransmit any outstanding packets */
514 /* Remove from queue if maxretrans exceeded */
515 time_t now;
516 struct qmsg_t *qmsg;
517 now = time(NULL);
518 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000519
Harald Welte95848ba2011-11-02 18:17:50 +0100520 /* get first element in queue, as long as the timeout of that
521 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100522 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
523 (qmsg->timeout <= now)) {
524 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100525 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100526 if (gsn->cb_conf)
527 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
528 queue_freemsg(gsn->queue_req, qmsg);
529 } else {
530 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
531 (struct sockaddr *)&qmsg->peer,
532 sizeof(struct sockaddr_in)) < 0) {
533 gsn->err_sendto++;
534 gtp_err(LOG_ERR, __FILE__, __LINE__,
535 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s",
536 gsn->fd0, (unsigned long)&qmsg->p,
537 qmsg->l, strerror(errno));
538 }
539 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100540 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100541 qmsg->retrans++;
542 }
543 }
jjako52c24142002-12-16 13:33:51 +0000544
Harald Weltebed35df2011-11-02 13:06:18 +0100545 /* Also clean up reply timeouts */
546 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
547 (qmsg->timeout < now)) {
548 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
549 queue_freemsg(gsn->queue_resp, qmsg);
550 }
jjako52c24142002-12-16 13:33:51 +0000551
Harald Weltebed35df2011-11-02 13:06:18 +0100552 return 0;
jjako52c24142002-12-16 13:33:51 +0000553}
554
Harald Weltebed35df2011-11-02 13:06:18 +0100555int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
556{
557 time_t now, later;
558 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000559
Harald Weltebed35df2011-11-02 13:06:18 +0100560 if (queue_getfirst(gsn->queue_req, &qmsg)) {
561 timeout->tv_sec = 10;
562 timeout->tv_usec = 0;
563 } else {
564 now = time(NULL);
565 later = qmsg->timeout;
566 timeout->tv_sec = later - now;
567 timeout->tv_usec = 0;
568 if (timeout->tv_sec < 0)
569 timeout->tv_sec = 0; /* No negative allowed */
570 if (timeout->tv_sec > 10)
571 timeout->tv_sec = 10; /* Max sleep for 10 sec */
572 }
573 return 0;
jjako52c24142002-12-16 13:33:51 +0000574}
575
Harald Weltebed35df2011-11-02 13:06:18 +0100576int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000577 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100578 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
579{
580 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000581
Harald Weltebed35df2011-11-02 13:06:18 +0100582 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
583 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
584 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100585 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100586 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
587 (packet->gtp0.h.type == GTP_ERROR)))
588 packet->gtp0.h.flow = hton16(pdp->flru);
589 else if (pdp)
590 packet->gtp0.h.flow = hton16(pdp->flrc);
591 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
592 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
593 packet->gtp1l.h.seq = hton16(seq);
594 if (pdp && (fd == gsn->fd1u))
595 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
596 else if (pdp)
597 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
598 } else {
599 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
600 return -1;
601 }
jjako08d331d2003-10-13 20:33:30 +0000602
Harald Weltebed35df2011-11-02 13:06:18 +0100603 if (fcntl(fd, F_SETFL, 0)) {
604 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
605 return -1;
606 }
jjako52c24142002-12-16 13:33:51 +0000607
Harald Weltebed35df2011-11-02 13:06:18 +0100608 if (sendto(fd, packet, len, 0,
609 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
610 gsn->err_sendto++;
611 gtp_err(LOG_ERR, __FILE__, __LINE__,
612 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
613 (unsigned long)&packet, len, strerror(errno));
614 return -1;
615 }
616
617 /* Use new queue structure */
618 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
619 gsn->err_queuefull++;
620 gtp_err(LOG_ERR, __FILE__, __LINE__,
621 "Retransmit queue is full");
622 } else {
623 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
624 qmsg->l = len;
625 qmsg->timeout = time(NULL) + 60; /* When to timeout */
626 qmsg->retrans = 0; /* No retransmissions so far */
627 qmsg->cbp = NULL;
628 qmsg->type = 0;
629 qmsg->fd = fd;
630 }
631 return 0;
jjako52c24142002-12-16 13:33:51 +0000632}
633
jjako2c381332003-10-21 19:09:53 +0000634int gtp_notification(struct gsn_t *gsn, int version,
635 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100636 struct sockaddr_in *peer, int fd, uint16_t seq)
637{
jjako2c381332003-10-21 19:09:53 +0000638
Harald Weltebed35df2011-11-02 13:06:18 +0100639 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000640
Harald Weltebed35df2011-11-02 13:06:18 +0100641 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000642
Harald Weltebed35df2011-11-02 13:06:18 +0100643 /* In GTP0 notifications are treated as replies. In GTP1 they
644 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000645
Harald Weltebed35df2011-11-02 13:06:18 +0100646 if (fd == gsn->fd1c)
647 addr.sin_port = htons(GTP1C_PORT);
648 else if (fd == gsn->fd1u)
649 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000650
Harald Weltebed35df2011-11-02 13:06:18 +0100651 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
652 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
653 packet->gtp0.h.seq = hton16(seq);
654 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
655 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
656 packet->gtp1l.h.seq = hton16(seq);
657 } else {
658 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
659 return -1;
660 }
661
662 if (fcntl(fd, F_SETFL, 0)) {
663 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
664 return -1;
665 }
666
667 if (sendto(fd, packet, len, 0,
668 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
669 gsn->err_sendto++;
670 gtp_err(LOG_ERR, __FILE__, __LINE__,
671 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
672 (unsigned long)&packet, len, strerror(errno));
673 return -1;
674 }
675 return 0;
jjako2c381332003-10-21 19:09:53 +0000676}
677
Harald Weltebed35df2011-11-02 13:06:18 +0100678int gtp_dublicate(struct gsn_t *gsn, int version,
679 struct sockaddr_in *peer, uint16_t seq)
680{
681 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000682
Harald Weltebed35df2011-11-02 13:06:18 +0100683 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
684 return EOF; /* Notfound */
685 }
jjakoa7cd2492003-04-11 09:40:12 +0000686
Harald Weltebed35df2011-11-02 13:06:18 +0100687 if (fcntl(qmsg->fd, F_SETFL, 0)) {
688 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
689 return -1;
690 }
691
692 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
693 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
694 gsn->err_sendto++;
695 gtp_err(LOG_ERR, __FILE__, __LINE__,
696 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s",
697 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
698 strerror(errno));
699 }
700 return 0;
jjako52c24142002-12-16 13:33:51 +0000701}
702
jjako52c24142002-12-16 13:33:51 +0000703/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100704static void log_restart(struct gsn_t *gsn)
705{
jjako52c24142002-12-16 13:33:51 +0000706 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200707 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000708 int counter = 0;
709 char filename[NAMESIZE];
710
Harald Weltebed35df2011-11-02 13:06:18 +0100711 filename[NAMESIZE - 1] = 0; /* No null term. guarantee by strncpy */
712 strncpy(filename, gsn->statedir, NAMESIZE - 1);
713 strncat(filename, RESTART_FILE, NAMESIZE - 1 - sizeof(RESTART_FILE));
jjako52c24142002-12-16 13:33:51 +0000714
715 i = umask(022);
716
717 /* We try to open file. On failure we will later try to create file */
718 if (!(f = fopen(filename, "r"))) {
jjako581c9f02003-10-22 11:28:20 +0000719
Harald Weltebed35df2011-11-02 13:06:18 +0100720 gtp_err(LOG_ERR, __FILE__, __LINE__,
721 "State information file (%s) not found. Creating new file.",
722 filename);
723 } else {
724 umask(i);
725 rc = fscanf(f, "%d", &counter);
726 if (rc != 1) {
727 gtp_err(LOG_ERR, __FILE__, __LINE__,
728 "fscanf failed to read counter value");
729 return;
730 }
731 if (fclose(f)) {
732 gtp_err(LOG_ERR, __FILE__, __LINE__,
733 "fclose failed: Error = %s", strerror(errno));
734 }
jjako52c24142002-12-16 13:33:51 +0000735 }
Harald Weltebed35df2011-11-02 13:06:18 +0100736
737 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000738 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100739
jjako52c24142002-12-16 13:33:51 +0000740 if (!(f = fopen(filename, "w"))) {
Harald Weltebed35df2011-11-02 13:06:18 +0100741 gtp_err(LOG_ERR, __FILE__, __LINE__,
742 "fopen(path=%s, mode=%s) failed: Error = %s", filename,
743 "w", strerror(errno));
744 return;
jjako52c24142002-12-16 13:33:51 +0000745 }
746
747 umask(i);
748 fprintf(f, "%d\n", gsn->restart_counter);
749 if (fclose(f)) {
Harald Weltebed35df2011-11-02 13:06:18 +0100750 gtp_err(LOG_ERR, __FILE__, __LINE__,
751 "fclose failed: Error = %s", strerror(errno));
752 return;
jjako52c24142002-12-16 13:33:51 +0000753 }
754}
755
jjako1db1c812003-07-06 20:53:57 +0000756int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100757 int mode)
jjako52c24142002-12-16 13:33:51 +0000758{
Harald Weltebed35df2011-11-02 13:06:18 +0100759 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000760
Harald Weltebed35df2011-11-02 13:06:18 +0100761 syslog(LOG_ERR, "GTP: gtp_newgsn() started");
jjako52c24142002-12-16 13:33:51 +0000762
Harald Weltebed35df2011-11-02 13:06:18 +0100763 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000764
Harald Weltebed35df2011-11-02 13:06:18 +0100765 (*gsn)->statedir = statedir;
766 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000767
Harald Weltebed35df2011-11-02 13:06:18 +0100768 /* Initialise sequence number */
769 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000770
Harald Weltebed35df2011-11-02 13:06:18 +0100771 /* Initialise request retransmit queue */
772 queue_new(&(*gsn)->queue_req);
773 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000774
Harald Weltebed35df2011-11-02 13:06:18 +0100775 /* Initialise pdp table */
776 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000777
Harald Weltebed35df2011-11-02 13:06:18 +0100778 /* Initialise call back functions */
779 (*gsn)->cb_create_context_ind = 0;
780 (*gsn)->cb_delete_context = 0;
781 (*gsn)->cb_unsup_ind = 0;
782 (*gsn)->cb_conf = 0;
783 (*gsn)->cb_data_ind = 0;
784
785 /* Store function parameters */
786 (*gsn)->gsnc = *listen;
787 (*gsn)->gsnu = *listen;
788 (*gsn)->mode = mode;
789
790 /* Create GTP version 0 socket */
791 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
792 (*gsn)->err_socket++;
793 gtp_err(LOG_ERR, __FILE__, __LINE__,
794 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
795 AF_INET, SOCK_DGRAM, 0, strerror(errno));
796 return -1;
797 }
798
799 memset(&addr, 0, sizeof(addr));
800 addr.sin_family = AF_INET;
801 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
802 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000803#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100804 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000805#endif
jjako08d331d2003-10-13 20:33:30 +0000806
Harald Weltebed35df2011-11-02 13:06:18 +0100807 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
808 (*gsn)->err_socket++;
809 gtp_err(LOG_ERR, __FILE__, __LINE__,
810 "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s",
811 (*gsn)->fd0, (unsigned long)&addr, sizeof(addr),
812 strerror(errno));
813 return -1;
814 }
jjako08d331d2003-10-13 20:33:30 +0000815
Harald Weltebed35df2011-11-02 13:06:18 +0100816 /* Create GTP version 1 control plane socket */
817 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
818 (*gsn)->err_socket++;
819 gtp_err(LOG_ERR, __FILE__, __LINE__,
820 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
821 AF_INET, SOCK_DGRAM, 0, strerror(errno));
822 return -1;
823 }
824
825 memset(&addr, 0, sizeof(addr));
826 addr.sin_family = AF_INET;
827 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
828 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000829#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100830 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000831#endif
jjako08d331d2003-10-13 20:33:30 +0000832
Harald Weltebed35df2011-11-02 13:06:18 +0100833 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
834 (*gsn)->err_socket++;
835 gtp_err(LOG_ERR, __FILE__, __LINE__,
836 "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
837 (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
838 strerror(errno));
839 return -1;
840 }
jjako08d331d2003-10-13 20:33:30 +0000841
Harald Weltebed35df2011-11-02 13:06:18 +0100842 /* Create GTP version 1 user plane socket */
843 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
844 (*gsn)->err_socket++;
845 gtp_err(LOG_ERR, __FILE__, __LINE__,
846 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
847 AF_INET, SOCK_DGRAM, 0, strerror(errno));
848 return -1;
849 }
850
851 memset(&addr, 0, sizeof(addr));
852 addr.sin_family = AF_INET;
853 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
854 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000855#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100856 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000857#endif
jjako52c24142002-12-16 13:33:51 +0000858
Harald Weltebed35df2011-11-02 13:06:18 +0100859 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
860 (*gsn)->err_socket++;
861 gtp_err(LOG_ERR, __FILE__, __LINE__,
862 "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
863 (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
864 strerror(errno));
865 return -1;
866 }
867
868 return 0;
jjako52c24142002-12-16 13:33:51 +0000869}
870
Harald Weltebed35df2011-11-02 13:06:18 +0100871int gtp_free(struct gsn_t *gsn)
872{
jjako52c24142002-12-16 13:33:51 +0000873
Harald Weltebed35df2011-11-02 13:06:18 +0100874 /* Clean up retransmit queues */
875 queue_free(gsn->queue_req);
876 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000877
Harald Weltebed35df2011-11-02 13:06:18 +0100878 close(gsn->fd0);
879 close(gsn->fd1c);
880 close(gsn->fd1u);
881
882 free(gsn);
883 return 0;
jjako52c24142002-12-16 13:33:51 +0000884}
885
886/* ***********************************************************
887 * Path management messages
888 * Messages: echo and version not supported.
889 * A path is connection between two UDP/IP endpoints
890 *
891 * A path is either using GTP0 or GTP1. A path can be
892 * established by any kind of GTP message??
893
894 * Which source port to use?
895 * GTP-C request destination port is 2123/3386
896 * GTP-U request destination port is 2152/3386
897 * T-PDU destination port is 2152/3386.
898 * For the above messages the source port is locally allocated.
899 * For response messages src=rx-dst and dst=rx-src.
900 * For simplicity we should probably use 2123+2152/3386 as
901 * src port even for the cases where src can be locally
902 * allocated. This also means that we have to listen only to
903 * the same ports.
904 * For response messages we need to be able to respond to
905 * the relevant src port even if it is locally allocated by
906 * the peer.
907 *
908 * The need for path management!
909 * We might need to keep a list of active paths. This might
910 * be in the form of remote IP address + UDP port numbers.
911 * (We will consider a path astablished if we have a context
912 * with the node in question)
913 *************************************************************/
914
915/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000916int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
917 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000918{
Harald Weltebed35df2011-11-02 13:06:18 +0100919 union gtp_packet packet;
920 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
921 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000922}
923
jjako08d331d2003-10-13 20:33:30 +0000924/* Send off an echo reply */
925int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100926 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000927{
Harald Weltebed35df2011-11-02 13:06:18 +0100928 union gtp_packet packet;
929 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
930 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
931 gsn->restart_counter);
932 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
933 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000934}
935
jjako52c24142002-12-16 13:33:51 +0000936/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100937int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
938 int fd, void *pack, unsigned len)
939{
jjako52c24142002-12-16 13:33:51 +0000940
Harald Weltebed35df2011-11-02 13:06:18 +0100941 /* Check if it was a dublicate request */
942 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
943 return 0;
jjako52c24142002-12-16 13:33:51 +0000944
Harald Weltebed35df2011-11-02 13:06:18 +0100945 /* Send off reply to request */
946 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000947}
948
949/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000950int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100951 void *pack, unsigned len)
952{
953 union gtpie_member *ie[GTPIE_SIZE];
954 unsigned char recovery;
955 void *cbp = NULL;
956 uint8_t type = 0;
957 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000958
Harald Weltebed35df2011-11-02 13:06:18 +0100959 /* Remove packet from queue */
960 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
961 return EOF;
jjako52c24142002-12-16 13:33:51 +0000962
Harald Weltebed35df2011-11-02 13:06:18 +0100963 /* Extract information elements into a pointer array */
964 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
965 gsn->invalid++;
966 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
967 "Invalid message format");
968 if (gsn->cb_conf)
969 gsn->cb_conf(type, EOF, NULL, cbp);
970 return EOF;
971 }
jjako52c24142002-12-16 13:33:51 +0000972
Harald Weltebed35df2011-11-02 13:06:18 +0100973 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
974 gsn->missing++;
975 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
976 "Missing mandatory field");
977 if (gsn->cb_conf)
978 gsn->cb_conf(type, EOF, NULL, cbp);
979 return EOF;
980 }
jjako52c24142002-12-16 13:33:51 +0000981
Harald Weltebed35df2011-11-02 13:06:18 +0100982 /* Echo reply packages does not have a cause information element */
983 /* Instead we return the recovery number in the callback function */
984 if (gsn->cb_conf)
985 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100986
Harald Weltebed35df2011-11-02 13:06:18 +0100987 if (gsn->cb_recovery)
988 gsn->cb_recovery(peer, recovery);
989
990 return 0;
jjako52c24142002-12-16 13:33:51 +0000991}
992
993/* Send off a Version Not Supported message */
994/* This message is somewhat special in that it actually is a
995 * response to some other message with unsupported GTP version
996 * For this reason it has parameters like a response, and does
997 * its own message transmission. No signalling queue is used
998 * The reply is sent to the peer IP and peer UDP. This means that
999 * the peer will be receiving a GTP0 message on a GTP1 port!
1000 * In practice however this will never happen as a GTP0 GSN will
1001 * only listen to the GTP0 port, and therefore will never receive
1002 * anything else than GTP0 */
1003
jjako08d331d2003-10-13 20:33:30 +00001004int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1005 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001006{
Harald Weltebed35df2011-11-02 13:06:18 +01001007 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001008
Harald Weltebed35df2011-11-02 13:06:18 +01001009 /* GTP 1 is the highest supported protocol */
1010 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1011 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001012}
1013
1014/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001015int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1016 void *pack, unsigned len)
1017{
jjako52c24142002-12-16 13:33:51 +00001018
Harald Weltebed35df2011-11-02 13:06:18 +01001019 if (gsn->cb_unsup_ind)
1020 gsn->cb_unsup_ind(peer);
1021
1022 return 0;
jjako52c24142002-12-16 13:33:51 +00001023}
1024
jjako2c381332003-10-21 19:09:53 +00001025/* Send off an Supported Extension Headers Notification */
1026int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1027 int fd, void *pack, unsigned len)
1028{
Harald Weltebed35df2011-11-02 13:06:18 +01001029 union gtp_packet packet;
1030 unsigned int length =
1031 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001032
Harald Weltebed35df2011-11-02 13:06:18 +01001033 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001034
Harald Weltebed35df2011-11-02 13:06:18 +01001035 if (version < 1)
1036 return 0;
jjako2c381332003-10-21 19:09:53 +00001037
Harald Weltebed35df2011-11-02 13:06:18 +01001038 /* We report back that we support only PDCP PDU headers */
1039 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1040 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001041
Harald Weltebed35df2011-11-02 13:06:18 +01001042 return gtp_notification(gsn, version, &packet, length,
1043 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001044}
1045
1046/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +01001047int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1048 void *pack, unsigned len)
1049{
jjako2c381332003-10-21 19:09:53 +00001050
Harald Weltebed35df2011-11-02 13:06:18 +01001051 if (gsn->cb_extheader_ind)
1052 gsn->cb_extheader_ind(peer);
1053
1054 return 0;
jjako2c381332003-10-21 19:09:53 +00001055}
1056
jjako52c24142002-12-16 13:33:51 +00001057/* ***********************************************************
1058 * Session management messages
1059 * Messages: create, update and delete PDP context
1060 *
1061 * Information storage
1062 * Information storage for each PDP context is defined in
1063 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1064 * PDP-address (IP address), sequence numbers, charging ID.
1065 * For the SGSN it also includes radio related mobility
1066 * information.
1067 *************************************************************/
1068
Harald Welte7b3347b2010-05-15 12:18:46 +02001069/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001070extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1071 void *cbp)
1072{
1073 union gtp_packet packet;
1074 unsigned int length =
1075 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1076 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001077
Harald Weltebed35df2011-11-02 13:06:18 +01001078 /* TODO: Secondary PDP Context Activation Procedure */
1079 /* In secondary activation procedure the PDP context is identified
1080 by tei in the header. The following fields are omitted: Selection
1081 mode, IMSI, MSISDN, End User Address, Access Point Name and
1082 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001083
Harald Weltebed35df2011-11-02 13:06:18 +01001084 if (pdp->secondary) {
1085 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
1086 gtp_err(LOG_ERR, __FILE__, __LINE__,
1087 "Unknown linked PDP context");
1088 return EOF;
1089 }
1090 }
jjako2c381332003-10-21 19:09:53 +00001091
Harald Weltebed35df2011-11-02 13:06:18 +01001092 if (pdp->version == 0) {
1093 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1094 sizeof(pdp->qos_req0), pdp->qos_req0);
1095 }
jjako52c24142002-12-16 13:33:51 +00001096
Harald Weltebed35df2011-11-02 13:06:18 +01001097 /* Section 7.7.2 */
1098 if (pdp->version == 1) {
1099 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1100 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1101 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1102 }
jjako52c24142002-12-16 13:33:51 +00001103
Harald Weltebed35df2011-11-02 13:06:18 +01001104 /* Section 7.7.3 Routing Area Information */
1105 if (pdp->rai_given == 1)
1106 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1107 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001108
Harald Weltebed35df2011-11-02 13:06:18 +01001109 /* Section 7.7.11 */
1110 if (pdp->norecovery_given == 0)
1111 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1112 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001113
Harald Weltebed35df2011-11-02 13:06:18 +01001114 /* Section 7.7.12 */
1115 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1116 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1117 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001118
Harald Weltebed35df2011-11-02 13:06:18 +01001119 if (pdp->version == 0) {
1120 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1121 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1122 }
jjako08d331d2003-10-13 20:33:30 +00001123
Harald Weltebed35df2011-11-02 13:06:18 +01001124 /* Section 7.7.13 */
1125 if (pdp->version == 1) {
1126 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1127 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001128
Harald Weltebed35df2011-11-02 13:06:18 +01001129 /* Section 7.7.14 */
1130 if (!pdp->teic_confirmed)
1131 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1132 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001133
Harald Weltebed35df2011-11-02 13:06:18 +01001134 /* Section 7.7.17 */
1135 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001136
Harald Weltebed35df2011-11-02 13:06:18 +01001137 /* Section 7.7.17 */
1138 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1139 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1140 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001141
Harald Weltebed35df2011-11-02 13:06:18 +01001142 /* Section 7.7.23 */
1143 if (pdp->cch_pdp) /* Only include charging if flags are set */
1144 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1145 pdp->cch_pdp);
1146 }
jjako9b4971d2004-05-27 20:30:19 +00001147
Harald Weltebed35df2011-11-02 13:06:18 +01001148 /* TODO
1149 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1150 pdp->traceref);
1151 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1152 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001153
Harald Weltebed35df2011-11-02 13:06:18 +01001154 /* Section 7.7.27 */
1155 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1156 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1157 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001158
Harald Weltebed35df2011-11-02 13:06:18 +01001159 /* Section 7.7.30 */
1160 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1161 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1162 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001163
Harald Weltebed35df2011-11-02 13:06:18 +01001164 /* Section 7.7.31 */
1165 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1166 if (pdp->pco_req.l)
1167 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1168 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001169
Harald Weltebed35df2011-11-02 13:06:18 +01001170 /* Section 7.7.32 */
1171 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1172 pdp->gsnlc.l, pdp->gsnlc.v);
1173 /* Section 7.7.32 */
1174 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1175 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001176
Harald Weltebed35df2011-11-02 13:06:18 +01001177 /* Section 7.7.33 */
1178 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1179 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1180 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001181
Harald Weltebed35df2011-11-02 13:06:18 +01001182 /* Section 7.7.34 */
1183 if (pdp->version == 1)
1184 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1185 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001186
Harald Weltebed35df2011-11-02 13:06:18 +01001187 /* Section 7.7.36 */
1188 if ((pdp->version == 1) && pdp->tft.l)
1189 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1190 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001191
Harald Weltebed35df2011-11-02 13:06:18 +01001192 /* Section 7.7.41 */
1193 if ((pdp->version == 1) && pdp->triggerid.l)
1194 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1195 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001196
Harald Weltebed35df2011-11-02 13:06:18 +01001197 /* Section 7.7.42 */
1198 if ((pdp->version == 1) && pdp->omcid.l)
1199 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1200 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001201
Harald Weltebed35df2011-11-02 13:06:18 +01001202 /* new R7 fields */
1203 if (pdp->rattype_given == 1)
1204 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1205 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001206
Harald Weltebed35df2011-11-02 13:06:18 +01001207 if (pdp->userloc_given == 1)
1208 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1209 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001210
Harald Weltebed35df2011-11-02 13:06:18 +01001211 if (pdp->mstz_given == 1)
1212 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1213 pdp->mstz.l, pdp->mstz.v);
1214
1215 if (pdp->imeisv_given == 1)
1216 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1217 pdp->imeisv.l, pdp->imeisv.v);
1218
1219 /* TODO hisaddr0 */
1220 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1221
1222 return 0;
jjako52c24142002-12-16 13:33:51 +00001223}
1224
jjako08d331d2003-10-13 20:33:30 +00001225/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001226int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1227{
jjako08d331d2003-10-13 20:33:30 +00001228
Harald Weltebed35df2011-11-02 13:06:18 +01001229 /* Now send off a reply to the peer */
1230 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1231
1232 if (cause != GTPCAUSE_ACC_REQ) {
1233 pdp_freepdp(pdp);
1234 }
1235
1236 return 0;
jjako08d331d2003-10-13 20:33:30 +00001237}
1238
1239/* API: Register create context indication callback */
1240int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001241 int (*cb_create_context_ind) (struct pdp_t *
1242 pdp))
jjako52c24142002-12-16 13:33:51 +00001243{
Harald Weltebed35df2011-11-02 13:06:18 +01001244 gsn->cb_create_context_ind = cb_create_context_ind;
1245 return 0;
jjako08d331d2003-10-13 20:33:30 +00001246}
1247
jjako08d331d2003-10-13 20:33:30 +00001248/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001249int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1250 uint8_t cause)
1251{
1252 union gtp_packet packet;
1253 unsigned int length =
1254 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001255
Harald Weltebed35df2011-11-02 13:06:18 +01001256 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001257
Harald Weltebed35df2011-11-02 13:06:18 +01001258 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001259
Harald Weltebed35df2011-11-02 13:06:18 +01001260 if (version == 0)
1261 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1262 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001263
Harald Weltebed35df2011-11-02 13:06:18 +01001264 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1265 pdp->reorder);
1266 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1267 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 if (version == 0) {
1270 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1271 pdp->fllu);
1272 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1273 pdp->fllc);
1274 }
jjako08d331d2003-10-13 20:33:30 +00001275
Harald Weltebed35df2011-11-02 13:06:18 +01001276 if (version == 1) {
1277 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1278 pdp->teid_own);
1279 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1280 pdp->teic_own);
1281 }
jjako08d331d2003-10-13 20:33:30 +00001282
Harald Weltebed35df2011-11-02 13:06:18 +01001283 /* TODO: We use teic_own as charging ID */
1284 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1285 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001286
Harald Weltebed35df2011-11-02 13:06:18 +01001287 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1288 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001289
Harald Weltebed35df2011-11-02 13:06:18 +01001290 if (pdp->pco_neg.l) { /* Optional PCO */
1291 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1292 pdp->pco_neg.l, pdp->pco_neg.v);
1293 }
jjako52c24142002-12-16 13:33:51 +00001294
Harald Weltebed35df2011-11-02 13:06:18 +01001295 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1296 pdp->gsnlc.l, pdp->gsnlc.v);
1297 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1298 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001299
Harald Weltebed35df2011-11-02 13:06:18 +01001300 if (version == 1)
1301 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1302 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001303
Harald Weltebed35df2011-11-02 13:06:18 +01001304 /* TODO: Charging gateway address */
1305 }
jjako52c24142002-12-16 13:33:51 +00001306
Harald Weltebed35df2011-11-02 13:06:18 +01001307 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1308 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001309}
1310
1311/* Handle Create PDP Context Request */
1312int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001313 struct sockaddr_in *peer, int fd,
1314 void *pack, unsigned len)
1315{
1316 struct pdp_t *pdp, *pdp_old;
1317 struct pdp_t pdp_buf;
1318 union gtpie_member *ie[GTPIE_SIZE];
1319 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001320
Harald Weltebed35df2011-11-02 13:06:18 +01001321 uint16_t seq = get_seq(pack);
1322 int hlen = get_hlen(pack);
1323 uint8_t linked_nsapi = 0;
1324 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001325
Harald Weltebed35df2011-11-02 13:06:18 +01001326 if (!gtp_dublicate(gsn, version, peer, seq))
1327 return 0;
jjako08d331d2003-10-13 20:33:30 +00001328
Harald Weltebed35df2011-11-02 13:06:18 +01001329 pdp = &pdp_buf;
1330 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001331
Harald Weltebed35df2011-11-02 13:06:18 +01001332 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001333 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1334
1335 pdp->imsi = tid & 0x0fffffffffffffffull;
1336 pdp->nsapi = (tid & 0xf000000000000000ull) >> 60;
Harald Weltebed35df2011-11-02 13:06:18 +01001337 }
jjako52c24142002-12-16 13:33:51 +00001338
Harald Weltebed35df2011-11-02 13:06:18 +01001339 pdp->seq = seq;
1340 pdp->sa_peer = *peer;
1341 pdp->fd = fd;
1342 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001343
Harald Weltebed35df2011-11-02 13:06:18 +01001344 /* Decode information elements */
1345 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1346 gsn->invalid++;
1347 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1348 "Invalid message format");
1349 if (0 == version)
1350 return EOF;
1351 else
1352 return gtp_create_pdp_resp(gsn, version, pdp,
1353 GTPCAUSE_INVALID_MESSAGE);
1354 }
jjako52c24142002-12-16 13:33:51 +00001355
Harald Weltebed35df2011-11-02 13:06:18 +01001356 if (version == 1) {
1357 /* Linked NSAPI (conditional) */
1358 /* If included this is the Secondary PDP Context Activation Procedure */
1359 /* In secondary activation IMSI is not included, so the context must be */
1360 /* identified by the tei */
1361 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001362
Harald Weltebed35df2011-11-02 13:06:18 +01001363 /* Find the primary PDP context */
1364 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1365 gsn->incorrect++;
1366 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1367 pack, len,
1368 "Incorrect optional information field");
1369 return gtp_create_pdp_resp(gsn, version, pdp,
1370 GTPCAUSE_OPT_IE_INCORRECT);
1371 }
jjako2c381332003-10-21 19:09:53 +00001372
Harald Weltebed35df2011-11-02 13:06:18 +01001373 /* Check that the primary PDP context matches linked nsapi */
1374 if (linked_pdp->nsapi != linked_nsapi) {
1375 gsn->incorrect++;
1376 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1377 pack, len,
1378 "Incorrect optional information field");
1379 return gtp_create_pdp_resp(gsn, version, pdp,
1380 GTPCAUSE_OPT_IE_INCORRECT);
1381 }
jjako52c24142002-12-16 13:33:51 +00001382
Harald Weltebed35df2011-11-02 13:06:18 +01001383 /* Copy parameters from primary context */
1384 pdp->selmode = linked_pdp->selmode;
1385 pdp->imsi = linked_pdp->imsi;
1386 pdp->msisdn = linked_pdp->msisdn;
1387 pdp->eua = linked_pdp->eua;
1388 pdp->pco_req = linked_pdp->pco_req;
1389 pdp->apn_req = linked_pdp->apn_req;
1390 pdp->teic_gn = linked_pdp->teic_gn;
1391 pdp->secondary = 1;
1392 }
1393 }
1394 /* if (version == 1) */
1395 if (version == 0) {
1396 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1397 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1398 gsn->missing++;
1399 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1400 len, "Missing mandatory information field");
1401 return gtp_create_pdp_resp(gsn, version, pdp,
1402 GTPCAUSE_MAN_IE_MISSING);
1403 }
1404 }
jjako08d331d2003-10-13 20:33:30 +00001405
Harald Weltebed35df2011-11-02 13:06:18 +01001406 if ((version == 1) && (!linked_pdp)) {
1407 /* Not Secondary PDP Context Activation Procedure */
1408 /* IMSI (conditional) */
1409 if (gtpie_gettv0
1410 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1411 gsn->missing++;
1412 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1413 len, "Missing mandatory information field");
1414 return gtp_create_pdp_resp(gsn, version, pdp,
1415 GTPCAUSE_MAN_IE_MISSING);
1416 }
1417 }
jjako52c24142002-12-16 13:33:51 +00001418
Harald Weltebed35df2011-11-02 13:06:18 +01001419 /* Recovery (optional) */
1420 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1421 if (gsn->cb_recovery)
1422 gsn->cb_recovery(peer, recovery);
1423 }
jjako52c24142002-12-16 13:33:51 +00001424
Harald Weltebed35df2011-11-02 13:06:18 +01001425 /* Selection mode (conditional) */
1426 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1427 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1428 &pdp->selmode, sizeof(pdp->selmode))) {
1429 gsn->missing++;
1430 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1431 len, "Missing mandatory information field");
1432 return gtp_create_pdp_resp(gsn, version, pdp,
1433 GTPCAUSE_MAN_IE_MISSING);
1434 }
1435 }
jjako52c24142002-12-16 13:33:51 +00001436
Harald Weltebed35df2011-11-02 13:06:18 +01001437 if (version == 0) {
1438 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1439 gsn->missing++;
1440 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1441 len, "Missing mandatory information field");
1442 return gtp_create_pdp_resp(gsn, version, pdp,
1443 GTPCAUSE_MAN_IE_MISSING);
1444 }
jjako52c24142002-12-16 13:33:51 +00001445
Harald Weltebed35df2011-11-02 13:06:18 +01001446 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1447 gsn->missing++;
1448 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1449 len, "Missing mandatory information field");
1450 return gtp_create_pdp_resp(gsn, version, pdp,
1451 GTPCAUSE_MAN_IE_MISSING);
1452 }
1453 }
jjako08d331d2003-10-13 20:33:30 +00001454
Harald Weltebed35df2011-11-02 13:06:18 +01001455 if (version == 1) {
1456 /* TEID (mandatory) */
1457 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1458 gsn->missing++;
1459 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1460 len, "Missing mandatory information field");
1461 return gtp_create_pdp_resp(gsn, version, pdp,
1462 GTPCAUSE_MAN_IE_MISSING);
1463 }
jjako2c381332003-10-21 19:09:53 +00001464
Harald Weltebed35df2011-11-02 13:06:18 +01001465 /* TEIC (conditional) */
1466 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1467 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1468 gsn->missing++;
1469 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1470 pack, len,
1471 "Missing mandatory information field");
1472 return gtp_create_pdp_resp(gsn, version, pdp,
1473 GTPCAUSE_MAN_IE_MISSING);
1474 }
1475 }
jjako08d331d2003-10-13 20:33:30 +00001476
Harald Weltebed35df2011-11-02 13:06:18 +01001477 /* NSAPI (mandatory) */
1478 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1479 gsn->missing++;
1480 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1481 len, "Missing mandatory information field");
1482 return gtp_create_pdp_resp(gsn, version, pdp,
1483 GTPCAUSE_MAN_IE_MISSING);
1484 }
1485 }
jjako2e840a32003-01-28 16:05:18 +00001486
Harald Weltebed35df2011-11-02 13:06:18 +01001487 /* Charging Characteriatics (optional) */
1488 /* Trace reference (optional) */
1489 /* Trace type (optional) */
1490 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001491
Harald Weltebed35df2011-11-02 13:06:18 +01001492 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1493 /* End User Address (conditional) */
1494 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1495 &pdp->eua.v, sizeof(pdp->eua.v))) {
1496 gsn->missing++;
1497 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1498 len, "Missing mandatory information field");
1499 return gtp_create_pdp_resp(gsn, version, pdp,
1500 GTPCAUSE_MAN_IE_MISSING);
1501 }
jjako08d331d2003-10-13 20:33:30 +00001502
Harald Weltebed35df2011-11-02 13:06:18 +01001503 /* APN */
1504 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1505 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1506 gsn->missing++;
1507 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1508 len, "Missing mandatory information field");
1509 return gtp_create_pdp_resp(gsn, version, pdp,
1510 GTPCAUSE_MAN_IE_MISSING);
1511 }
jjako2c381332003-10-21 19:09:53 +00001512
Harald Weltebed35df2011-11-02 13:06:18 +01001513 /* Extract protocol configuration options (optional) */
1514 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1515 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1516 }
1517 }
jjako2c381332003-10-21 19:09:53 +00001518
Harald Weltebed35df2011-11-02 13:06:18 +01001519 /* SGSN address for signalling (mandatory) */
1520 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1521 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1522 gsn->missing++;
1523 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1524 "Missing mandatory information field");
1525 return gtp_create_pdp_resp(gsn, version, pdp,
1526 GTPCAUSE_MAN_IE_MISSING);
1527 }
jjako2e840a32003-01-28 16:05:18 +00001528
Harald Weltebed35df2011-11-02 13:06:18 +01001529 /* SGSN address for user traffic (mandatory) */
1530 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1531 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1532 gsn->missing++;
1533 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1534 "Missing mandatory information field");
1535 return gtp_create_pdp_resp(gsn, version, pdp,
1536 GTPCAUSE_MAN_IE_MISSING);
1537 }
jjako52c24142002-12-16 13:33:51 +00001538
Harald Weltebed35df2011-11-02 13:06:18 +01001539 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1540 /* MSISDN (conditional) */
1541 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1542 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1543 gsn->missing++;
1544 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1545 len, "Missing mandatory information field");
1546 return gtp_create_pdp_resp(gsn, version, pdp,
1547 GTPCAUSE_MAN_IE_MISSING);
1548 }
1549 }
jjako52c24142002-12-16 13:33:51 +00001550
Harald Weltebed35df2011-11-02 13:06:18 +01001551 if (version == 1) {
1552 /* QoS (mandatory) */
1553 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1554 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1555 gsn->missing++;
1556 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1557 len, "Missing mandatory information field");
1558 return gtp_create_pdp_resp(gsn, version, pdp,
1559 GTPCAUSE_MAN_IE_MISSING);
1560 }
1561
1562 /* TFT (conditional) */
1563 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1564 &pdp->tft.v, sizeof(pdp->tft.v))) {
1565 }
1566
1567 /* Trigger ID */
1568 /* OMC identity */
1569 }
1570
1571 /* Initialize our own IP addresses */
1572 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1573 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1574
1575 if (GTP_DEBUG)
1576 printf("gtp_create_pdp_ind: Before pdp_tidget\n");
1577
1578 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1579 /* Found old pdp with same tid. Now the voodoo begins! */
1580 /* 09.60 / 29.060 allows create on existing context to "steal" */
1581 /* the context which was allready established */
1582 /* We check that the APN, selection mode and MSISDN is the same */
1583 if (GTP_DEBUG)
1584 printf("gtp_create_pdp_ind: Old context found\n");
1585 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1586 &&
1587 (!memcmp
1588 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1589 && (pdp->selmode == pdp_old->selmode)
1590 && (pdp->msisdn.l == pdp_old->msisdn.l)
1591 &&
1592 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1593 {
1594 /* OK! We are dealing with the same APN. We will copy new
1595 * parameters to the old pdp and send off confirmation
1596 * We ignore the following information elements:
1597 * QoS: MS will get originally negotiated QoS.
1598 * End user address (EUA). MS will get old EUA anyway.
1599 * Protocol configuration option (PCO): Only application can verify */
1600
1601 if (GTP_DEBUG)
1602 printf
1603 ("gtp_create_pdp_ind: Old context found\n");
1604
1605 /* Copy remote flow label */
1606 pdp_old->flru = pdp->flru;
1607 pdp_old->flrc = pdp->flrc;
1608
1609 /* Copy remote tei */
1610 pdp_old->teid_gn = pdp->teid_gn;
1611 pdp_old->teic_gn = pdp->teic_gn;
1612
1613 /* Copy peer GSN address */
1614 pdp_old->gsnrc.l = pdp->gsnrc.l;
1615 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1616 pdp_old->gsnru.l = pdp->gsnru.l;
1617 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1618
1619 /* Copy request parameters */
1620 pdp_old->seq = pdp->seq;
1621 pdp_old->sa_peer = pdp->sa_peer;
1622 pdp_old->fd = pdp->fd = fd;
1623 pdp_old->version = pdp->version = version;
1624
1625 /* Switch to using the old pdp context */
1626 pdp = pdp_old;
1627
1628 /* Confirm to peer that things were "successful" */
1629 return gtp_create_pdp_resp(gsn, version, pdp,
1630 GTPCAUSE_ACC_REQ);
1631 } else { /* This is not the same PDP context. Delete the old one. */
1632
1633 if (GTP_DEBUG)
1634 printf
1635 ("gtp_create_pdp_ind: Deleting old context\n");
1636
1637 if (gsn->cb_delete_context)
1638 gsn->cb_delete_context(pdp_old);
1639 pdp_freepdp(pdp_old);
1640
1641 if (GTP_DEBUG)
1642 printf("gtp_create_pdp_ind: Deleted...\n");
1643 }
1644 }
1645
1646 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1647
1648 /* Callback function to validata login */
1649 if (gsn->cb_create_context_ind != 0)
1650 return gsn->cb_create_context_ind(pdp);
1651 else {
1652 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1653 "No create_context_ind callback defined");
1654 return gtp_create_pdp_resp(gsn, version, pdp,
1655 GTPCAUSE_NOT_SUPPORTED);
1656 }
jjako52c24142002-12-16 13:33:51 +00001657}
1658
jjako52c24142002-12-16 13:33:51 +00001659/* Handle Create PDP Context Response */
1660int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001661 struct sockaddr_in *peer, void *pack, unsigned len)
1662{
1663 struct pdp_t *pdp;
1664 union gtpie_member *ie[GTPIE_SIZE];
1665 uint8_t cause, recovery;
1666 void *cbp = NULL;
1667 uint8_t type = 0;
1668 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001669
Harald Weltebed35df2011-11-02 13:06:18 +01001670 /* Remove packet from queue */
1671 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1672 return EOF;
jjako52c24142002-12-16 13:33:51 +00001673
Harald Weltebed35df2011-11-02 13:06:18 +01001674 /* Find the context in question */
1675 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1676 gsn->err_unknownpdp++;
1677 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1678 "Unknown PDP context");
1679 if (gsn->cb_conf)
1680 gsn->cb_conf(type, EOF, NULL, cbp);
1681 return EOF;
1682 }
jjako2c381332003-10-21 19:09:53 +00001683
Harald Weltebed35df2011-11-02 13:06:18 +01001684 /* Register that we have received a valid teic from GGSN */
1685 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001686
Harald Weltebed35df2011-11-02 13:06:18 +01001687 /* Decode information elements */
1688 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1689 gsn->invalid++;
1690 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1691 "Invalid message format");
1692 if (gsn->cb_conf)
1693 gsn->cb_conf(type, EOF, pdp, cbp);
1694 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1695 pdp_freepdp(pdp); */
1696 return EOF;
1697 }
jjako52c24142002-12-16 13:33:51 +00001698
Harald Weltebed35df2011-11-02 13:06:18 +01001699 /* Extract cause value (mandatory) */
1700 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1701 gsn->missing++;
1702 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1703 "Missing mandatory information field");
1704 if (gsn->cb_conf)
1705 gsn->cb_conf(type, EOF, pdp, cbp);
1706 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1707 pdp_freepdp(pdp); */
1708 return EOF;
1709 }
jjako52c24142002-12-16 13:33:51 +00001710
Harald Weltebed35df2011-11-02 13:06:18 +01001711 /* Extract recovery (optional) */
1712 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1713 if (gsn->cb_recovery)
1714 gsn->cb_recovery(peer, recovery);
1715 }
jjako52c24142002-12-16 13:33:51 +00001716
Harald Weltebed35df2011-11-02 13:06:18 +01001717 /* Extract protocol configuration options (optional) */
1718 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1719 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1720 }
jjako52c24142002-12-16 13:33:51 +00001721
Harald Weltebed35df2011-11-02 13:06:18 +01001722 /* Check all conditional information elements */
1723 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001724
Harald Weltebed35df2011-11-02 13:06:18 +01001725 if (version == 0) {
1726 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1727 &pdp->qos_neg0,
1728 sizeof(pdp->qos_neg0))) {
1729 gsn->missing++;
1730 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1731 pack, len,
1732 "Missing conditional information field");
1733 if (gsn->cb_conf)
1734 gsn->cb_conf(type, EOF, pdp, cbp);
1735 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1736 pdp_freepdp(pdp); */
1737 return EOF;
1738 }
1739 }
jjako08d331d2003-10-13 20:33:30 +00001740
Harald Weltebed35df2011-11-02 13:06:18 +01001741 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1742 gsn->missing++;
1743 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1744 len,
1745 "Missing conditional information field");
1746 if (gsn->cb_conf)
1747 gsn->cb_conf(type, EOF, pdp, cbp);
1748 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1749 pdp_freepdp(pdp); */
1750 return EOF;
1751 }
jjako52c24142002-12-16 13:33:51 +00001752
Harald Weltebed35df2011-11-02 13:06:18 +01001753 if (version == 0) {
1754 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1755 gsn->missing++;
1756 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1757 pack, len,
1758 "Missing conditional information field");
1759 if (gsn->cb_conf)
1760 gsn->cb_conf(type, EOF, pdp, cbp);
1761 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1762 pdp_freepdp(pdp); */
1763 return EOF;
1764 }
jjako52c24142002-12-16 13:33:51 +00001765
Harald Weltebed35df2011-11-02 13:06:18 +01001766 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1767 gsn->missing++;
1768 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1769 pack, len,
1770 "Missing conditional information field");
1771 if (gsn->cb_conf)
1772 gsn->cb_conf(type, EOF, pdp, cbp);
1773 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1774 pdp_freepdp(pdp); */
1775 return EOF;
1776 }
1777 }
1778
1779 if (version == 1) {
1780 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1781 gsn->missing++;
1782 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1783 pack, len,
1784 "Missing conditional information field");
1785 if (gsn->cb_conf)
1786 gsn->cb_conf(type, EOF, pdp, cbp);
1787 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1788 pdp_freepdp(pdp); */
1789 return EOF;
1790 }
1791
1792 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1793 gsn->missing++;
1794 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1795 pack, len,
1796 "Missing conditional information field");
1797 if (gsn->cb_conf)
1798 gsn->cb_conf(type, EOF, pdp, cbp);
1799 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1800 pdp_freepdp(pdp); */
1801 return EOF;
1802 }
1803 }
1804
1805 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1806 gsn->missing++;
1807 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1808 len,
1809 "Missing conditional information field");
1810 if (gsn->cb_conf)
1811 gsn->cb_conf(type, EOF, pdp, cbp);
1812 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1813 pdp_freepdp(pdp); */
1814 }
1815
1816 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1817 &pdp->eua.v, sizeof(pdp->eua.v))) {
1818 gsn->missing++;
1819 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1820 len,
1821 "Missing conditional information field");
1822 if (gsn->cb_conf)
1823 gsn->cb_conf(type, EOF, pdp, cbp);
1824 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1825 pdp_freepdp(pdp); */
1826 return EOF;
1827 }
1828
1829 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1830 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1831 gsn->missing++;
1832 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1833 len,
1834 "Missing conditional information field");
1835 if (gsn->cb_conf)
1836 gsn->cb_conf(type, EOF, pdp, cbp);
1837 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1838 pdp_freepdp(pdp); */
1839 return EOF;
1840 }
1841
1842 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1843 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1844 gsn->missing++;
1845 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1846 len,
1847 "Missing conditional information field");
1848 if (gsn->cb_conf)
1849 gsn->cb_conf(type, EOF, pdp, cbp);
1850 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1851 pdp_freepdp(pdp); */
1852 return EOF;
1853 }
1854
1855 if (version == 1) {
1856 if (gtpie_gettlv
1857 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1858 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1859 gsn->missing++;
1860 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1861 pack, len,
1862 "Missing conditional information field");
1863 if (gsn->cb_conf)
1864 gsn->cb_conf(type, EOF, pdp, cbp);
1865 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1866 pdp_freepdp(pdp); */
1867 return EOF;
1868 }
1869 }
1870
1871 }
1872
1873 if (gsn->cb_conf)
1874 gsn->cb_conf(type, cause, pdp, cbp);
1875
1876 return 0;
jjako52c24142002-12-16 13:33:51 +00001877}
1878
jjako08d331d2003-10-13 20:33:30 +00001879/* API: Send Update PDP Context Request */
1880int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001881 struct in_addr *inetaddr)
1882{
1883 union gtp_packet packet;
1884 unsigned int length =
1885 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001886
Harald Weltebed35df2011-11-02 13:06:18 +01001887 if (pdp->version == 0)
1888 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1889 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001890
Harald Weltebed35df2011-11-02 13:06:18 +01001891 /* Include IMSI if updating with unknown teic_gn */
1892 if ((pdp->version == 1) && (!pdp->teic_gn))
1893 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1894 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1895
1896 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1897 gsn->restart_counter);
1898
1899 if (pdp->version == 0) {
1900 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1901 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1902 }
1903
1904 if (pdp->version == 1) {
1905 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1906 pdp->teid_own);
1907
1908 if (!pdp->teic_confirmed)
1909 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1910 pdp->teic_own);
1911 }
1912
1913 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1914
1915 /* TODO
1916 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1917 pdp->traceref);
1918 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1919 pdp->tracetype); */
1920
1921 /* TODO if ggsn update message
1922 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1923 pdp->eua.l, pdp->eua.v);
1924 */
1925
1926 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1927 pdp->gsnlc.l, pdp->gsnlc.v);
1928 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1929 pdp->gsnlu.l, pdp->gsnlu.v);
1930
1931 if (pdp->version == 1)
1932 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1933 pdp->qos_req.l, pdp->qos_req.v);
1934
1935 if ((pdp->version == 1) && pdp->tft.l)
1936 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1937 pdp->tft.l, pdp->tft.v);
1938
1939 if ((pdp->version == 1) && pdp->triggerid.l)
1940 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1941 pdp->triggerid.l, pdp->triggerid.v);
1942
1943 if ((pdp->version == 1) && pdp->omcid.l)
1944 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1945 pdp->omcid.l, pdp->omcid.v);
1946
1947 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1948
1949 return 0;
jjako52c24142002-12-16 13:33:51 +00001950}
1951
jjako08d331d2003-10-13 20:33:30 +00001952/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001953int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1954 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001955 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001956 struct pdp_t *pdp, uint8_t cause)
1957{
jjako08d331d2003-10-13 20:33:30 +00001958
Harald Weltebed35df2011-11-02 13:06:18 +01001959 union gtp_packet packet;
1960 unsigned int length =
1961 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001962
Harald Weltebed35df2011-11-02 13:06:18 +01001963 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001964
Harald Weltebed35df2011-11-02 13:06:18 +01001965 if (cause == GTPCAUSE_ACC_REQ) {
1966
1967 if (version == 0)
1968 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1969 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1970
1971 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1972 gsn->restart_counter);
1973
1974 if (version == 0) {
1975 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1976 pdp->fllu);
1977 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1978 pdp->fllc);
1979 }
1980
1981 if (version == 1) {
1982 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1983 pdp->teid_own);
1984
1985 if (!pdp->teic_confirmed)
1986 gtpie_tv4(&packet, &length, GTP_MAX,
1987 GTPIE_TEI_C, pdp->teic_own);
1988 }
1989
1990 /* TODO we use teid_own as charging ID address */
1991 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1992 pdp->teid_own);
1993
1994 /* If ggsn
1995 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1996 pdp->eua.l, pdp->eua.v); */
1997
1998 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1999 pdp->gsnlc.l, pdp->gsnlc.v);
2000 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2001 pdp->gsnlu.l, pdp->gsnlu.v);
2002
2003 if (version == 1)
2004 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2005 pdp->qos_neg.l, pdp->qos_neg.v);
2006
2007 /* TODO: Charging gateway address */
2008 }
2009
2010 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2011 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002012}
2013
jjako52c24142002-12-16 13:33:51 +00002014/* Handle Update PDP Context Request */
2015int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002016 struct sockaddr_in *peer, int fd,
2017 void *pack, unsigned len)
2018{
2019 struct pdp_t *pdp;
2020 struct pdp_t pdp_backup;
2021 union gtpie_member *ie[GTPIE_SIZE];
2022 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002023
Harald Weltebed35df2011-11-02 13:06:18 +01002024 uint16_t seq = get_seq(pack);
2025 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002026
Harald Weltebed35df2011-11-02 13:06:18 +01002027 uint64_t imsi;
2028 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002029
Harald Weltebed35df2011-11-02 13:06:18 +01002030 /* Is this a dublicate ? */
2031 if (!gtp_dublicate(gsn, version, peer, seq)) {
2032 return 0; /* We allready send of response once */
2033 }
jjako08d331d2003-10-13 20:33:30 +00002034
Harald Weltebed35df2011-11-02 13:06:18 +01002035 /* Decode information elements */
2036 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2037 gsn->invalid++;
2038 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2039 "Invalid message format");
2040 if (0 == version)
2041 return EOF;
2042 else
2043 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2044 len, NULL,
2045 GTPCAUSE_INVALID_MESSAGE);
2046 }
jjako08d331d2003-10-13 20:33:30 +00002047
Harald Weltebed35df2011-11-02 13:06:18 +01002048 /* Finding PDP: */
2049 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2050 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2051 /* we have to use the tunnel endpoint identifier */
2052 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002053 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2054
2055 imsi = tid & 0x0fffffffffffffffull;
2056 nsapi = (tid & 0xf000000000000000ull) >> 60;
jjako52c24142002-12-16 13:33:51 +00002057
Harald Weltebed35df2011-11-02 13:06:18 +01002058 /* Find the context in question */
2059 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2060 gsn->err_unknownpdp++;
2061 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2062 len, "Unknown PDP context");
2063 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2064 len, NULL,
2065 GTPCAUSE_NON_EXIST);
2066 }
2067 } else if (version == 1) {
2068 /* NSAPI (mandatory) */
2069 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2070 gsn->missing++;
2071 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2072 len, "Missing mandatory information field");
2073 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2074 len, NULL,
2075 GTPCAUSE_MAN_IE_MISSING);
2076 }
jjako08d331d2003-10-13 20:33:30 +00002077
Harald Weltebed35df2011-11-02 13:06:18 +01002078 /* IMSI (conditional) */
2079 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2080 /* Find the context in question */
2081 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2082 gsn->err_unknownpdp++;
2083 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
2084 pack, len, "Unknown PDP context");
2085 return gtp_update_pdp_resp(gsn, version, peer,
2086 fd, pack, len, NULL,
2087 GTPCAUSE_NON_EXIST);
2088 }
2089 } else {
2090 /* Find the context in question */
2091 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2092 gsn->err_unknownpdp++;
2093 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
2094 pack, len, "Unknown PDP context");
2095 return gtp_update_pdp_resp(gsn, version, peer,
2096 fd, pack, len, NULL,
2097 GTPCAUSE_NON_EXIST);
2098 }
2099 }
2100 } else {
2101 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
2102 return EOF;
2103 }
jjako08d331d2003-10-13 20:33:30 +00002104
Harald Weltebed35df2011-11-02 13:06:18 +01002105 /* Make a backup copy in case anything is wrong */
2106 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002107
Harald Weltebed35df2011-11-02 13:06:18 +01002108 if (version == 0) {
2109 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2110 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2111 gsn->missing++;
2112 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2113 len, "Missing mandatory information field");
2114 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2115 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2116 len, pdp,
2117 GTPCAUSE_MAN_IE_MISSING);
2118 }
2119 }
jjako52c24142002-12-16 13:33:51 +00002120
Harald Weltebed35df2011-11-02 13:06:18 +01002121 /* Recovery (optional) */
2122 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2123 if (gsn->cb_recovery)
2124 gsn->cb_recovery(peer, recovery);
2125 }
jjako08d331d2003-10-13 20:33:30 +00002126
Harald Weltebed35df2011-11-02 13:06:18 +01002127 if (version == 0) {
2128 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2129 gsn->missing++;
2130 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2131 len, "Missing mandatory information field");
2132 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2133 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2134 len, pdp,
2135 GTPCAUSE_MAN_IE_MISSING);
2136 }
jjako52c24142002-12-16 13:33:51 +00002137
Harald Weltebed35df2011-11-02 13:06:18 +01002138 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2139 gsn->missing++;
2140 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2141 len, "Missing mandatory information field");
2142 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2143 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2144 len, pdp,
2145 GTPCAUSE_MAN_IE_MISSING);
2146 }
2147 }
jjako52c24142002-12-16 13:33:51 +00002148
Harald Weltebed35df2011-11-02 13:06:18 +01002149 if (version == 1) {
2150 /* TEID (mandatory) */
2151 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2152 gsn->missing++;
2153 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2154 len, "Missing mandatory information field");
2155 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2156 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2157 len, pdp,
2158 GTPCAUSE_MAN_IE_MISSING);
2159 }
jjako52c24142002-12-16 13:33:51 +00002160
Harald Weltebed35df2011-11-02 13:06:18 +01002161 /* TEIC (conditional) */
2162 /* If TEIC is not included it means that we have allready received it */
2163 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2164 /* all updated contexts, or only for one of the linked contexts */
2165 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2166
2167 /* NSAPI (mandatory) */
2168 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2169 gsn->missing++;
2170 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2171 len, "Missing mandatory information field");
2172 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2173 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2174 len, pdp,
2175 GTPCAUSE_MAN_IE_MISSING);
2176 }
2177 }
2178
2179 /* Trace reference (optional) */
2180 /* Trace type (optional) */
2181
2182 /* End User Address (conditional) TODO: GGSN Initiated
2183 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2184 &pdp->eua.v, sizeof(pdp->eua.v))) {
2185 gsn->missing++;
2186 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2187 "Missing mandatory information field");
2188 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2189 return gtp_update_pdp_resp(gsn, version, pdp,
2190 GTPCAUSE_MAN_IE_MISSING);
2191 } */
2192
2193 /* SGSN address for signalling (mandatory) */
2194 /* It is weird that this is mandatory when TEIC is conditional */
2195 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2196 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2197 gsn->missing++;
2198 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2199 "Missing mandatory information field");
2200 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2201 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2202 pdp, GTPCAUSE_MAN_IE_MISSING);
2203 }
2204
2205 /* SGSN address for user traffic (mandatory) */
2206 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2207 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2208 gsn->missing++;
2209 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2210 "Missing mandatory information field");
2211 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2212 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2213 pdp, GTPCAUSE_MAN_IE_MISSING);
2214 }
2215
2216 if (version == 1) {
2217 /* QoS (mandatory) */
2218 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2219 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2220 gsn->missing++;
2221 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2222 len, "Missing mandatory information field");
2223 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2224 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2225 len, pdp,
2226 GTPCAUSE_MAN_IE_MISSING);
2227 }
2228
2229 /* TFT (conditional) */
2230 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2231 &pdp->tft.v, sizeof(pdp->tft.v))) {
2232 }
2233
2234 /* OMC identity */
2235 }
2236
2237 /* Confirm to peer that things were "successful" */
2238 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2239 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002240}
2241
jjako52c24142002-12-16 13:33:51 +00002242/* Handle Update PDP Context Response */
2243int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002244 struct sockaddr_in *peer, void *pack, unsigned len)
2245{
2246 struct pdp_t *pdp;
2247 union gtpie_member *ie[GTPIE_SIZE];
2248 uint8_t cause, recovery;
2249 void *cbp = NULL;
2250 uint8_t type = 0;
jjako52c24142002-12-16 13:33:51 +00002251
Harald Weltebed35df2011-11-02 13:06:18 +01002252 /* Remove packet from queue */
2253 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2254 return EOF;
jjako52c24142002-12-16 13:33:51 +00002255
Harald Weltebed35df2011-11-02 13:06:18 +01002256 /* Find the context in question */
2257 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2258 gsn->err_unknownpdp++;
2259 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2260 "Unknown PDP context");
2261 if (gsn->cb_conf)
2262 gsn->cb_conf(type, cause, NULL, cbp);
2263 return EOF;
2264 }
jjako2c381332003-10-21 19:09:53 +00002265
Harald Weltebed35df2011-11-02 13:06:18 +01002266 /* Register that we have received a valid teic from GGSN */
2267 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002268
Harald Weltebed35df2011-11-02 13:06:18 +01002269 /* Decode information elements */
2270 if (gtpie_decaps
2271 (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
2272 gsn->invalid++;
2273 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2274 "Invalid message format");
2275 if (gsn->cb_conf)
2276 gsn->cb_conf(type, EOF, pdp, cbp);
2277 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2278 pdp_freepdp(pdp); */
2279 return EOF;
2280 }
jjako52c24142002-12-16 13:33:51 +00002281
Harald Weltebed35df2011-11-02 13:06:18 +01002282 /* Extract cause value (mandatory) */
2283 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2284 gsn->missing++;
2285 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2286 "Missing mandatory information field");
2287 if (gsn->cb_conf)
2288 gsn->cb_conf(type, EOF, pdp, cbp);
2289 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2290 pdp_freepdp(pdp); */
2291 return EOF;
2292 }
jjako52c24142002-12-16 13:33:51 +00002293
Harald Weltebed35df2011-11-02 13:06:18 +01002294 /* Extract recovery (optional) */
2295 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2296 if (gsn->cb_recovery)
2297 gsn->cb_recovery(peer, recovery);
2298 }
2299
2300 /* Check all conditional information elements */
2301 if (GTPCAUSE_ACC_REQ != cause) {
2302 if (gsn->cb_conf)
2303 gsn->cb_conf(type, cause, pdp, cbp);
2304 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2305 pdp_freepdp(pdp); */
2306 return 0;
2307 } else {
2308 /* Check for missing conditionary information elements */
2309 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2310 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2311 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2312 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2313 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2314 gtpie_exist(ie, GTPIE_EUA, 0) &&
2315 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2316 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2317 gsn->missing++;
2318 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2319 len,
2320 "Missing conditional information field");
2321 if (gsn->cb_conf)
2322 gsn->cb_conf(type, EOF, pdp, cbp);
2323 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2324 pdp_freepdp(pdp); */
2325 return EOF;
2326 }
2327
2328 /* Update pdp with new values */
2329 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2330 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2331 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2332 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2333 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2334 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2335 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2336 &pdp->eua.v, sizeof(pdp->eua.v));
2337 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2338 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2339 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2340 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2341
2342 if (gsn->cb_conf)
2343 gsn->cb_conf(type, cause, pdp, cbp);
2344 return 0; /* Succes */
2345 }
jjako52c24142002-12-16 13:33:51 +00002346}
2347
jjako08d331d2003-10-13 20:33:30 +00002348/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002349int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002350 int teardown)
2351{
2352 union gtp_packet packet;
2353 unsigned int length =
2354 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2355 struct in_addr addr;
2356 struct pdp_t *linked_pdp;
2357 struct pdp_t *secondary_pdp;
2358 int n;
2359 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002360
Harald Weltebed35df2011-11-02 13:06:18 +01002361 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2362 gsn->err_address++;
2363 gtp_err(LOG_ERR, __FILE__, __LINE__,
2364 "GSN address conversion failed");
2365 return EOF;
jjako2c381332003-10-21 19:09:53 +00002366 }
jjako2c381332003-10-21 19:09:53 +00002367
Harald Weltebed35df2011-11-02 13:06:18 +01002368 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2369 gtp_err(LOG_ERR, __FILE__, __LINE__,
2370 "Unknown linked PDP context");
2371 return EOF;
2372 }
2373
2374 if (!teardown) {
2375 for (n = 0; n < PDP_MAXNSAPI; n++)
2376 if (linked_pdp->secondary_tei[n])
2377 count++;
2378 if (count <= 1) {
2379 gtp_err(LOG_ERR, __FILE__, __LINE__,
2380 "Must use teardown for last context");
2381 return EOF;
2382 }
2383 }
2384
2385 if (pdp->version == 1) {
2386 if (teardown)
2387 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2388 0xff);
2389
2390 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2391 }
2392
2393 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2394
2395 if (teardown) { /* Remove all contexts */
2396 for (n = 0; n < PDP_MAXNSAPI; n++) {
2397 if (linked_pdp->secondary_tei[n]) {
2398 if (pdp_getgtp1
2399 (&secondary_pdp,
2400 linked_pdp->secondary_tei[n])) {
2401 gtp_err(LOG_ERR, __FILE__, __LINE__,
2402 "Unknown secondary PDP context");
2403 return EOF;
2404 }
2405 if (linked_pdp != secondary_pdp) {
2406 if (gsn->cb_delete_context)
2407 gsn->cb_delete_context
2408 (secondary_pdp);
2409 pdp_freepdp(secondary_pdp);
2410 }
2411 }
2412 }
2413 if (gsn->cb_delete_context)
2414 gsn->cb_delete_context(linked_pdp);
2415 pdp_freepdp(linked_pdp);
2416 } else {
2417 if (gsn->cb_delete_context)
2418 gsn->cb_delete_context(pdp);
2419 if (pdp == linked_pdp) {
2420 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2421 linked_pdp->nodata = 1;
2422 } else
2423 pdp_freepdp(pdp);
2424 }
2425
2426 return 0;
jjako2c381332003-10-21 19:09:53 +00002427}
jjako08d331d2003-10-13 20:33:30 +00002428
jjako52c24142002-12-16 13:33:51 +00002429/* Send Delete PDP Context Response */
2430int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002431 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002432 void *pack, unsigned len,
2433 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002434 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002435{
Harald Weltebed35df2011-11-02 13:06:18 +01002436 union gtp_packet packet;
2437 struct pdp_t *secondary_pdp;
2438 unsigned int length =
2439 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2440 int n;
jjako52c24142002-12-16 13:33:51 +00002441
Harald Weltebed35df2011-11-02 13:06:18 +01002442 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002443
Harald Weltebed35df2011-11-02 13:06:18 +01002444 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2445 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002446
Harald Weltebed35df2011-11-02 13:06:18 +01002447 if (cause == GTPCAUSE_ACC_REQ) {
2448 if ((teardown) || (version == 0)) { /* Remove all contexts */
2449 for (n = 0; n < PDP_MAXNSAPI; n++) {
2450 if (linked_pdp->secondary_tei[n]) {
2451 if (pdp_getgtp1
2452 (&secondary_pdp,
2453 linked_pdp->secondary_tei[n])) {
2454 gtp_err(LOG_ERR, __FILE__,
2455 __LINE__,
2456 "Unknown secondary PDP context");
2457 return EOF;
2458 }
2459 if (linked_pdp != secondary_pdp) {
2460 if (gsn->cb_delete_context)
2461 gsn->cb_delete_context
2462 (secondary_pdp);
2463 pdp_freepdp(secondary_pdp);
2464 }
2465 }
2466 }
2467 if (gsn->cb_delete_context)
2468 gsn->cb_delete_context(linked_pdp);
2469 pdp_freepdp(linked_pdp);
2470 } else { /* Remove only current context */
2471 if (gsn->cb_delete_context)
2472 gsn->cb_delete_context(pdp);
2473 if (pdp == linked_pdp) {
2474 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2475 0;
2476 linked_pdp->nodata = 1;
2477 } else
2478 pdp_freepdp(pdp);
2479 }
jjako2c381332003-10-21 19:09:53 +00002480 }
Harald Weltebed35df2011-11-02 13:06:18 +01002481 /* if (cause == GTPCAUSE_ACC_REQ) */
2482 return 0;
jjako52c24142002-12-16 13:33:51 +00002483}
2484
2485/* Handle Delete PDP Context Request */
2486int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002487 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002488 void *pack, unsigned len)
2489{
2490 struct pdp_t *pdp = NULL;
2491 struct pdp_t *linked_pdp = NULL;
2492 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002493
Harald Weltebed35df2011-11-02 13:06:18 +01002494 uint16_t seq = get_seq(pack);
2495 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002496
Harald Weltebed35df2011-11-02 13:06:18 +01002497 uint8_t nsapi;
2498 uint8_t teardown = 0;
2499 int n;
2500 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002501
Harald Weltebed35df2011-11-02 13:06:18 +01002502 /* Is this a dublicate ? */
2503 if (!gtp_dublicate(gsn, version, peer, seq)) {
2504 return 0; /* We allready send off response once */
2505 }
jjako2c381332003-10-21 19:09:53 +00002506
Harald Weltebed35df2011-11-02 13:06:18 +01002507 /* Find the linked context in question */
2508 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2509 gsn->err_unknownpdp++;
2510 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2511 "Unknown PDP context");
2512 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2513 NULL, NULL, GTPCAUSE_NON_EXIST,
2514 teardown);
2515 }
jjako2c381332003-10-21 19:09:53 +00002516
Harald Weltebed35df2011-11-02 13:06:18 +01002517 /* If version 0 this is also the secondary context */
2518 if (version == 0)
2519 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002520
Harald Weltebed35df2011-11-02 13:06:18 +01002521 /* Decode information elements */
2522 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2523 gsn->invalid++;
2524 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2525 "Invalid message format");
2526 if (0 == version)
2527 return EOF;
2528 else
2529 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2530 len, NULL, NULL,
2531 GTPCAUSE_INVALID_MESSAGE,
2532 teardown);
2533 }
2534
2535 if (version == 1) {
2536 /* NSAPI (mandatory) */
2537 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2538 gsn->missing++;
2539 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2540 len, "Missing mandatory information field");
2541 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2542 len, NULL, NULL,
2543 GTPCAUSE_MAN_IE_MISSING,
2544 teardown);
2545 }
2546
2547 /* Find the context in question */
2548 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2549 gsn->err_unknownpdp++;
2550 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2551 len, "Unknown PDP context");
2552 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2553 len, NULL, NULL,
2554 GTPCAUSE_NON_EXIST,
2555 teardown);
2556 }
2557
2558 /* Teardown (conditional) */
2559 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2560
2561 if (!teardown) {
2562 for (n = 0; n < PDP_MAXNSAPI; n++)
2563 if (linked_pdp->secondary_tei[n])
2564 count++;
2565 if (count <= 1) {
2566 return 0; /* 29.060 7.3.5 Ignore message */
2567 }
2568 }
2569 }
2570
2571 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2572 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002573}
2574
jjako52c24142002-12-16 13:33:51 +00002575/* Handle Delete PDP Context Response */
2576int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002577 struct sockaddr_in *peer, void *pack, unsigned len)
2578{
2579 union gtpie_member *ie[GTPIE_SIZE];
2580 uint8_t cause;
2581 void *cbp = NULL;
2582 uint8_t type = 0;
2583 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002584
Harald Weltebed35df2011-11-02 13:06:18 +01002585 /* Remove packet from queue */
2586 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2587 return EOF;
jjako52c24142002-12-16 13:33:51 +00002588
Harald Weltebed35df2011-11-02 13:06:18 +01002589 /* Decode information elements */
2590 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2591 gsn->invalid++;
2592 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2593 "Invalid message format");
2594 if (gsn->cb_conf)
2595 gsn->cb_conf(type, EOF, NULL, cbp);
2596 return EOF;
2597 }
2598
2599 /* Extract cause value (mandatory) */
2600 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2601 gsn->missing++;
2602 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2603 "Missing mandatory information field");
2604 if (gsn->cb_conf)
2605 gsn->cb_conf(type, EOF, NULL, cbp);
2606 return EOF;
2607 }
2608
2609 /* Check the cause value (again) */
2610 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2611 gsn->err_cause++;
2612 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2613 "Unexpected cause value received: %d", cause);
2614 if (gsn->cb_conf)
2615 gsn->cb_conf(type, cause, NULL, cbp);
2616 return EOF;
2617 }
2618
2619 /* Callback function to notify application */
2620 if (gsn->cb_conf)
2621 gsn->cb_conf(type, cause, NULL, cbp);
2622
2623 return 0;
jjako52c24142002-12-16 13:33:51 +00002624}
2625
2626/* Send Error Indication (response to a GPDU message */
2627int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002628 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002629 void *pack, unsigned len)
2630{
Harald Weltebed35df2011-11-02 13:06:18 +01002631 union gtp_packet packet;
2632 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2633
2634 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2635 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002636}
2637
2638/* Handle Error Indication */
2639int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002640 struct sockaddr_in *peer, void *pack, unsigned len)
2641{
2642 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002643
Harald Weltebed35df2011-11-02 13:06:18 +01002644 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002645 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002646 gsn->err_unknownpdp++;
2647 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2648 "Unknown PDP context");
2649 return EOF;
2650 }
jjako52c24142002-12-16 13:33:51 +00002651
Harald Weltebed35df2011-11-02 13:06:18 +01002652 gsn->err_unknownpdp++; /* TODO: Change counter */
2653 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2654 "Received Error Indication");
2655
2656 if (gsn->cb_delete_context)
2657 gsn->cb_delete_context(pdp);
2658 pdp_freepdp(pdp);
2659 return 0;
jjako52c24142002-12-16 13:33:51 +00002660}
2661
2662int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002663 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2664{
jjako08d331d2003-10-13 20:33:30 +00002665
Harald Weltebed35df2011-11-02 13:06:18 +01002666 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002667
Harald Weltebed35df2011-11-02 13:06:18 +01002668 /* Need to include code to verify packet src and dest addresses */
2669 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002670
Harald Weltebed35df2011-11-02 13:06:18 +01002671 if (version == 0) {
2672 if (pdp_getgtp0
2673 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2674 gsn->err_unknownpdp++;
2675 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2676 len, "Unknown PDP context");
2677 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2678 len);
2679 }
2680 hlen = GTP0_HEADER_SIZE;
2681 } else if (version == 1) {
2682 if (pdp_getgtp1
2683 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2684 gsn->err_unknownpdp++;
2685 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2686 len, "Unknown PDP context");
2687 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2688 len);
2689 }
jjako08d331d2003-10-13 20:33:30 +00002690
Harald Weltebed35df2011-11-02 13:06:18 +01002691 /* Is this a long or a short header ? */
2692 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2693 hlen = GTP1_HEADER_SIZE_LONG;
2694 else
2695 hlen = GTP1_HEADER_SIZE_SHORT;
2696 } else {
2697 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2698 "Unknown version");
2699 }
jjako08d331d2003-10-13 20:33:30 +00002700
Harald Weltebed35df2011-11-02 13:06:18 +01002701 /* If the GPDU was not from the peer GSN tell him to delete context */
2702 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2703 gsn->err_unknownpdp++;
2704 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2705 "Unknown PDP context");
2706 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2707 }
jjako52c24142002-12-16 13:33:51 +00002708
Harald Weltebed35df2011-11-02 13:06:18 +01002709 /* Callback function */
2710 if (gsn->cb_data_ind != 0)
2711 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2712
2713 return 0;
jjako52c24142002-12-16 13:33:51 +00002714}
2715
jjako52c24142002-12-16 13:33:51 +00002716/* Receives GTP packet and sends off for further processing
2717 * Function will check the validity of the header. If the header
2718 * is not valid the packet is either dropped or a version not
2719 * supported is returned to the peer.
2720 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002721int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002722{
Harald Weltebed35df2011-11-02 13:06:18 +01002723 unsigned char buffer[PACKET_MAX];
2724 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002725 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002726 int status;
2727 struct gtp0_header *pheader;
2728 int version = 0; /* GTP version should be determined from header! */
2729 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002730
Harald Weltebed35df2011-11-02 13:06:18 +01002731 /* TODO: Need strategy of userspace buffering and blocking */
2732 /* Currently read is non-blocking and send is blocking. */
2733 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002734
Harald Weltebed35df2011-11-02 13:06:18 +01002735 while (1) { /* Loop until no more to read */
2736 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
2737 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2738 return -1;
2739 }
2740 peerlen = sizeof(peer);
2741 if ((status =
2742 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2743 (struct sockaddr *)&peer, &peerlen)) < 0) {
2744 if (errno == EAGAIN)
2745 return 0;
2746 gsn->err_readfrom++;
2747 gtp_err(LOG_ERR, __FILE__, __LINE__,
2748 "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
2749 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2750 status, status ? strerror(errno) : "No error");
2751 return -1;
2752 }
jjako1db1c812003-07-06 20:53:57 +00002753
Harald Weltebed35df2011-11-02 13:06:18 +01002754 /* Need at least 1 byte in order to check version */
2755 if (status < (1)) {
2756 gsn->empty++;
2757 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2758 status, "Discarding packet - too small");
2759 continue;
2760 }
jjako08d331d2003-10-13 20:33:30 +00002761
Harald Weltebed35df2011-11-02 13:06:18 +01002762 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002763
Harald Weltebed35df2011-11-02 13:06:18 +01002764 /* Version should be gtp0 (or earlier) */
2765 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2766 /* GTP 0 messages. If other version message is received we reply that we */
2767 /* only support version 0, implying that this is the only version */
2768 /* supported on this port */
2769 if (((pheader->flags & 0xe0) > 0x00)) {
2770 gsn->unsup++;
2771 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2772 status, "Unsupported GTP version");
2773 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2774 continue;
2775 }
2776
2777 /* Check length of gtp0 packet */
2778 if (status < GTP0_HEADER_SIZE) {
2779 gsn->tooshort++;
2780 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2781 status, "GTP0 packet too short");
2782 continue; /* Silently discard 29.60: 11.1.2 */
2783 }
2784
2785 /* Check packet length field versus length of packet */
2786 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2787 gsn->tooshort++;
2788 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2789 status,
2790 "GTP packet length field does not match actual length");
2791 continue; /* Silently discard */
2792 }
2793
2794 if ((gsn->mode == GTP_MODE_GGSN) &&
2795 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2796 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2797 (pheader->type == GTP_DELETE_PDP_RSP))) {
2798 gsn->unexpect++;
2799 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2800 status,
2801 "Unexpected GTP Signalling Message");
2802 continue; /* Silently discard 29.60: 11.1.4 */
2803 }
2804
2805 if ((gsn->mode == GTP_MODE_SGSN) &&
2806 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2807 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2808 (pheader->type == GTP_DELETE_PDP_REQ))) {
2809 gsn->unexpect++;
2810 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2811 status,
2812 "Unexpected GTP Signalling Message");
2813 continue; /* Silently discard 29.60: 11.1.4 */
2814 }
2815
2816 switch (pheader->type) {
2817 case GTP_ECHO_REQ:
2818 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2819 break;
2820 case GTP_ECHO_RSP:
2821 gtp_echo_conf(gsn, version, &peer, buffer, status);
2822 break;
2823 case GTP_NOT_SUPPORTED:
2824 gtp_unsup_ind(gsn, &peer, buffer, status);
2825 break;
2826 case GTP_CREATE_PDP_REQ:
2827 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2828 status);
2829 break;
2830 case GTP_CREATE_PDP_RSP:
2831 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2832 status);
2833 break;
2834 case GTP_UPDATE_PDP_REQ:
2835 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2836 status);
2837 break;
2838 case GTP_UPDATE_PDP_RSP:
2839 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2840 status);
2841 break;
2842 case GTP_DELETE_PDP_REQ:
2843 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2844 status);
2845 break;
2846 case GTP_DELETE_PDP_RSP:
2847 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2848 status);
2849 break;
2850 case GTP_ERROR:
2851 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2852 break;
2853 case GTP_GPDU:
2854 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2855 break;
2856 default:
2857 gsn->unknown++;
2858 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2859 status,
2860 "Unknown GTP message type received");
2861 break;
2862 }
2863 }
jjako08d331d2003-10-13 20:33:30 +00002864}
2865
jjako08d331d2003-10-13 20:33:30 +00002866int gtp_decaps1c(struct gsn_t *gsn)
2867{
Harald Weltebed35df2011-11-02 13:06:18 +01002868 unsigned char buffer[PACKET_MAX];
2869 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002870 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002871 int status;
2872 struct gtp1_header_short *pheader;
2873 int version = 1; /* TODO GTP version should be determined from header! */
2874 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002875
Harald Weltebed35df2011-11-02 13:06:18 +01002876 /* TODO: Need strategy of userspace buffering and blocking */
2877 /* Currently read is non-blocking and send is blocking. */
2878 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002879
Harald Weltebed35df2011-11-02 13:06:18 +01002880 while (1) { /* Loop until no more to read */
2881 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
2882 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2883 return -1;
2884 }
2885 peerlen = sizeof(peer);
2886 if ((status =
2887 recvfrom(fd, buffer, sizeof(buffer), 0,
2888 (struct sockaddr *)&peer, &peerlen)) < 0) {
2889 if (errno == EAGAIN)
2890 return 0;
2891 gsn->err_readfrom++;
2892 gtp_err(LOG_ERR, __FILE__, __LINE__,
2893 "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
2894 fd, (unsigned long)buffer, sizeof(buffer),
2895 status, status ? strerror(errno) : "No error");
2896 return -1;
2897 }
jjako08d331d2003-10-13 20:33:30 +00002898
Harald Weltebed35df2011-11-02 13:06:18 +01002899 /* Need at least 1 byte in order to check version */
2900 if (status < (1)) {
2901 gsn->empty++;
2902 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2903 status, "Discarding packet - too small");
2904 continue;
2905 }
jjako08d331d2003-10-13 20:33:30 +00002906
Harald Weltebed35df2011-11-02 13:06:18 +01002907 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002908
Harald Weltebed35df2011-11-02 13:06:18 +01002909 /* Version must be no larger than GTP 1 */
2910 if (((pheader->flags & 0xe0) > 0x20)) {
2911 gsn->unsup++;
2912 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2913 status, "Unsupported GTP version");
2914 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2915 /*29.60: 11.1.1 */
2916 continue;
2917 }
jjako08d331d2003-10-13 20:33:30 +00002918
Harald Weltebed35df2011-11-02 13:06:18 +01002919 /* Version must be at least GTP 1 */
2920 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2921 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2922 /* the message */
2923 if (((pheader->flags & 0xe0) < 0x20)) {
2924 gsn->unsup++;
2925 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2926 status, "Unsupported GTP version");
2927 continue;
2928 }
jjako08d331d2003-10-13 20:33:30 +00002929
Harald Weltebed35df2011-11-02 13:06:18 +01002930 /* Check packet flag field */
2931 if (((pheader->flags & 0xf7) != 0x32)) {
2932 gsn->unsup++;
2933 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2934 status, "Unsupported packet flag");
2935 continue;
2936 }
jjako2c381332003-10-21 19:09:53 +00002937
Harald Weltebed35df2011-11-02 13:06:18 +01002938 /* Check length of packet */
2939 if (status < GTP1_HEADER_SIZE_LONG) {
2940 gsn->tooshort++;
2941 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2942 status, "GTP packet too short");
2943 continue; /* Silently discard 29.60: 11.1.2 */
2944 }
jjako2c381332003-10-21 19:09:53 +00002945
Harald Weltebed35df2011-11-02 13:06:18 +01002946 /* Check packet length field versus length of packet */
2947 if (status !=
2948 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2949 gsn->tooshort++;
2950 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2951 status,
2952 "GTP packet length field does not match actual length");
2953 continue; /* Silently discard */
2954 }
jjako1db1c812003-07-06 20:53:57 +00002955
Harald Weltebed35df2011-11-02 13:06:18 +01002956 /* Check for extension headers */
2957 /* TODO: We really should cycle through the headers and determine */
2958 /* if any have the comprehension required flag set */
2959 if (((pheader->flags & 0x04) != 0x00)) {
2960 gsn->unsup++;
2961 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2962 status, "Unsupported extension header");
2963 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2964 status);
jjako1db1c812003-07-06 20:53:57 +00002965
Harald Weltebed35df2011-11-02 13:06:18 +01002966 continue;
2967 }
2968
2969 if ((gsn->mode == GTP_MODE_GGSN) &&
2970 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2971 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2972 (pheader->type == GTP_DELETE_PDP_RSP))) {
2973 gsn->unexpect++;
2974 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2975 status,
2976 "Unexpected GTP Signalling Message");
2977 continue; /* Silently discard 29.60: 11.1.4 */
2978 }
2979
2980 if ((gsn->mode == GTP_MODE_SGSN) &&
2981 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2982 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2983 (pheader->type == GTP_DELETE_PDP_REQ))) {
2984 gsn->unexpect++;
2985 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2986 status,
2987 "Unexpected GTP Signalling Message");
2988 continue; /* Silently discard 29.60: 11.1.4 */
2989 }
2990
2991 switch (pheader->type) {
2992 case GTP_ECHO_REQ:
2993 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2994 break;
2995 case GTP_ECHO_RSP:
2996 gtp_echo_conf(gsn, version, &peer, buffer, status);
2997 break;
2998 case GTP_NOT_SUPPORTED:
2999 gtp_unsup_ind(gsn, &peer, buffer, status);
3000 break;
3001 case GTP_SUPP_EXT_HEADER:
3002 gtp_extheader_ind(gsn, &peer, buffer, status);
3003 break;
3004 case GTP_CREATE_PDP_REQ:
3005 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3006 status);
3007 break;
3008 case GTP_CREATE_PDP_RSP:
3009 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3010 status);
3011 break;
3012 case GTP_UPDATE_PDP_REQ:
3013 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3014 status);
3015 break;
3016 case GTP_UPDATE_PDP_RSP:
3017 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3018 status);
3019 break;
3020 case GTP_DELETE_PDP_REQ:
3021 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3022 status);
3023 break;
3024 case GTP_DELETE_PDP_RSP:
3025 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3026 status);
3027 break;
3028 case GTP_ERROR:
3029 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3030 break;
3031 default:
3032 gsn->unknown++;
3033 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3034 status,
3035 "Unknown GTP message type received");
3036 break;
3037 }
3038 }
jjako52c24142002-12-16 13:33:51 +00003039}
3040
jjako08d331d2003-10-13 20:33:30 +00003041int gtp_decaps1u(struct gsn_t *gsn)
3042{
Harald Weltebed35df2011-11-02 13:06:18 +01003043 unsigned char buffer[PACKET_MAX];
3044 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003045 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003046 int status;
3047 struct gtp1_header_short *pheader;
3048 int version = 1; /* GTP version should be determined from header! */
3049 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003050
Harald Weltebed35df2011-11-02 13:06:18 +01003051 /* TODO: Need strategy of userspace buffering and blocking */
3052 /* Currently read is non-blocking and send is blocking. */
3053 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003054
Harald Weltebed35df2011-11-02 13:06:18 +01003055 while (1) { /* Loop until no more to read */
3056 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
3057 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3058 return -1;
3059 }
3060 peerlen = sizeof(peer);
3061 if ((status =
3062 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3063 (struct sockaddr *)&peer, &peerlen)) < 0) {
3064 if (errno == EAGAIN)
3065 return 0;
3066 gsn->err_readfrom++;
3067 gtp_err(LOG_ERR, __FILE__, __LINE__,
3068 "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
3069 gsn->fd1u, (unsigned long)buffer,
3070 sizeof(buffer), status,
3071 status ? strerror(errno) : "No error");
3072 return -1;
3073 }
jjako08d331d2003-10-13 20:33:30 +00003074
Harald Weltebed35df2011-11-02 13:06:18 +01003075 /* Need at least 1 byte in order to check version */
3076 if (status < (1)) {
3077 gsn->empty++;
3078 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3079 status, "Discarding packet - too small");
3080 continue;
3081 }
jjako08d331d2003-10-13 20:33:30 +00003082
Harald Weltebed35df2011-11-02 13:06:18 +01003083 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003084
Harald Weltebed35df2011-11-02 13:06:18 +01003085 /* Version must be no larger than GTP 1 */
3086 if (((pheader->flags & 0xe0) > 0x20)) {
3087 gsn->unsup++;
3088 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3089 status, "Unsupported GTP version");
3090 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3091 continue;
3092 }
jjako08d331d2003-10-13 20:33:30 +00003093
Harald Weltebed35df2011-11-02 13:06:18 +01003094 /* Version must be at least GTP 1 */
3095 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3096 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3097 /* the message */
3098 if (((pheader->flags & 0xe0) < 0x20)) {
3099 gsn->unsup++;
3100 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3101 status, "Unsupported GTP version");
3102 continue;
3103 }
jjako2c381332003-10-21 19:09:53 +00003104
Harald Weltebed35df2011-11-02 13:06:18 +01003105 /* Check packet flag field (allow both with and without sequence number) */
3106 if (((pheader->flags & 0xf5) != 0x30)) {
3107 gsn->unsup++;
3108 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3109 status, "Unsupported packet flag");
3110 continue;
3111 }
jjako2c381332003-10-21 19:09:53 +00003112
Harald Weltebed35df2011-11-02 13:06:18 +01003113 /* Check length of packet */
3114 if (status < GTP1_HEADER_SIZE_SHORT) {
3115 gsn->tooshort++;
3116 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3117 status, "GTP packet too short");
3118 continue; /* Silently discard 29.60: 11.1.2 */
3119 }
3120
3121 /* Check packet length field versus length of packet */
3122 if (status !=
3123 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3124 gsn->tooshort++;
3125 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3126 status,
3127 "GTP packet length field does not match actual length");
3128 continue; /* Silently discard */
3129 }
3130
3131 /* Check for extension headers */
3132 /* TODO: We really should cycle through the headers and determine */
3133 /* if any have the comprehension required flag set */
3134 if (((pheader->flags & 0x04) != 0x00)) {
3135 gsn->unsup++;
3136 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3137 status, "Unsupported extension header");
3138 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3139 status);
3140
3141 continue;
3142 }
3143
3144 switch (pheader->type) {
3145 case GTP_ECHO_REQ:
3146 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3147 break;
3148 case GTP_ECHO_RSP:
3149 gtp_echo_conf(gsn, version, &peer, buffer, status);
3150 break;
3151 case GTP_SUPP_EXT_HEADER:
3152 gtp_extheader_ind(gsn, &peer, buffer, status);
3153 break;
3154 case GTP_ERROR:
3155 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3156 break;
3157 /* Supported header extensions */
3158 case GTP_GPDU:
3159 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3160 break;
3161 default:
3162 gsn->unknown++;
3163 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3164 status,
3165 "Unknown GTP message type received");
3166 break;
3167 }
3168 }
jjako08d331d2003-10-13 20:33:30 +00003169}
3170
Harald Weltebed35df2011-11-02 13:06:18 +01003171int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003172{
Harald Weltebed35df2011-11-02 13:06:18 +01003173 union gtp_packet packet;
3174 struct sockaddr_in addr;
3175 int fd;
3176 int length;
jjako52c24142002-12-16 13:33:51 +00003177
Harald Weltebed35df2011-11-02 13:06:18 +01003178 memset(&addr, 0, sizeof(addr));
3179 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003180#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003181 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003182#endif
3183
Harald Weltebed35df2011-11-02 13:06:18 +01003184 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003185
Harald Weltebed35df2011-11-02 13:06:18 +01003186 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003187
Harald Weltebed35df2011-11-02 13:06:18 +01003188 length = GTP0_HEADER_SIZE + len;
3189 addr.sin_port = htons(GTP0_PORT);
3190 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003191
Harald Weltebed35df2011-11-02 13:06:18 +01003192 get_default_gtp(0, GTP_GPDU, &packet);
3193 packet.gtp0.h.length = hton16(len);
3194 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3195 packet.gtp0.h.flow = hton16(pdp->flru);
3196 packet.gtp0.h.tid =
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01003197 htobe64((pdp->imsi & 0x0fffffffffffffffull) +
3198 ((uint64_t) pdp->nsapi << 60));
jjako08d331d2003-10-13 20:33:30 +00003199
Harald Weltebed35df2011-11-02 13:06:18 +01003200 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3201 gsn->err_memcpy++;
3202 gtp_err(LOG_ERR, __FILE__, __LINE__,
3203 "Memcpy failed: %d > %d", len,
3204 sizeof(union gtp_packet) -
3205 sizeof(struct gtp0_header));
3206 return EOF;
3207 }
3208 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3209 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003210
Harald Weltebed35df2011-11-02 13:06:18 +01003211 length = GTP1_HEADER_SIZE_LONG + len;
3212 addr.sin_port = htons(GTP1U_PORT);
3213 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003214
Harald Weltebed35df2011-11-02 13:06:18 +01003215 get_default_gtp(1, GTP_GPDU, &packet);
3216 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3217 GTP1_HEADER_SIZE_LONG);
3218 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3219 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3220
3221 if (len >
3222 sizeof(union gtp_packet) -
3223 sizeof(struct gtp1_header_long)) {
3224 gsn->err_memcpy++;
3225 gtp_err(LOG_ERR, __FILE__, __LINE__,
3226 "Memcpy failed: %d > %d", len,
3227 sizeof(union gtp_packet) -
3228 sizeof(struct gtp0_header));
3229 return EOF;
3230 }
3231 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3232 } else {
3233 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
3234 return EOF;
3235 }
3236
3237 if (fcntl(fd, F_SETFL, 0)) {
3238 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3239 return -1;
3240 }
3241
3242 if (sendto(fd, &packet, length, 0,
3243 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3244 gsn->err_sendto++;
3245 gtp_err(LOG_ERR, __FILE__, __LINE__,
3246 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
3247 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3248 strerror(errno));
3249 return EOF;
3250 }
3251 return 0;
jjako52c24142002-12-16 13:33:51 +00003252}
3253
jjako52c24142002-12-16 13:33:51 +00003254/* ***********************************************************
3255 * Conversion functions
3256 *************************************************************/
3257
Harald Weltebed35df2011-11-02 13:06:18 +01003258int char2ul_t(char *src, struct ul_t dst)
3259{
3260 dst.l = strlen(src) + 1;
3261 dst.v = malloc(dst.l);
3262 dst.v[0] = dst.l - 1;
3263 memcpy(&dst.v[1], src, dst.v[0]);
3264 return 0;
jjako52c24142002-12-16 13:33:51 +00003265}
3266
3267/* ***********************************************************
3268 * IP address conversion functions
3269 * There exist several types of address representations:
3270 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3271 * Used for signalling address to mobile station. Supports IPv4
3272 * IPv6 x.25 etc. etc.
3273 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3274 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3275 * - in_addr: IPv4 address struct.
3276 * - sockaddr_in: Socket API representation of IP address and
3277 * port number.
3278 *************************************************************/
3279
Harald Weltebed35df2011-11-02 13:06:18 +01003280int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3281{
3282 eua->v[0] = 0xf1; /* IETF */
3283 eua->v[1] = 0x21; /* IPv4 */
3284 if (src) {
3285 eua->l = 6;
3286 memcpy(&eua->v[2], src, 4);
3287 } else {
3288 eua->l = 2;
3289 }
3290 return 0;
jjako52c24142002-12-16 13:33:51 +00003291}
3292
Harald Weltebed35df2011-11-02 13:06:18 +01003293int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3294{
3295 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3296 return -1; /* Not IPv4 address */
3297 memcpy(dst, &eua->v[2], 4);
3298 return 0;
jjako52c24142002-12-16 13:33:51 +00003299}
3300
Harald Weltebed35df2011-11-02 13:06:18 +01003301int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3302{
3303 memset(dst, 0, sizeof(struct in_addr));
3304 if (gsna->l != 4)
3305 return EOF; /* Return if not IPv4 */
3306 memcpy(dst, gsna->v, gsna->l);
3307 return 0;
jjako52c24142002-12-16 13:33:51 +00003308}
3309
Harald Weltebed35df2011-11-02 13:06:18 +01003310int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3311{
3312 memset(gsna, 0, sizeof(struct ul16_t));
3313 gsna->l = 4;
3314 memcpy(gsna->v, src, gsna->l);
3315 return 0;
jjako52c24142002-12-16 13:33:51 +00003316}