blob: 61856349be0bb967fecac5522a35bbfa7c9fe7a5 [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 Ayuso746b9442014-03-24 17:58:27 +0100430 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100431 }
Harald Weltebed35df2011-11-02 13:06:18 +0100432 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
433 || (packet->gtp0.h.type == GTP_ERROR)))
434 packet->gtp0.h.flow = hton16(pdp->flru);
435 else if (pdp)
436 packet->gtp0.h.flow = hton16(pdp->flrc);
437 fd = gsn->fd0;
438 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
439 addr.sin_port = htons(GTP1C_PORT);
440 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
441 packet->gtp1l.h.seq = hton16(gsn->seq_next);
442 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
443 (packet->gtp1l.h.type == GTP_ERROR)))
444 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
445 else if (pdp)
446 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
447 fd = gsn->fd1c;
448 } else {
449 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
450 return -1;
451 }
jjako52c24142002-12-16 13:33:51 +0000452
Harald Weltebed35df2011-11-02 13:06:18 +0100453 if (sendto(fd, packet, len, 0,
454 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
455 gsn->err_sendto++;
456 gtp_err(LOG_ERR, __FILE__, __LINE__,
457 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
458 (unsigned long)&packet, len, strerror(errno));
459 return -1;
460 }
461
462 /* Use new queue structure */
463 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
464 gsn->err_queuefull++;
465 gtp_err(LOG_ERR, __FILE__, __LINE__,
466 "Retransmit queue is full");
467 } else {
468 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
469 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100470 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100471 qmsg->retrans = 0; /* No retransmissions so far */
472 qmsg->cbp = cbp;
473 qmsg->type = ntoh8(packet->gtp0.h.type);
474 qmsg->fd = fd;
475 }
476 gsn->seq_next++; /* Count up this time */
477 return 0;
jjako52c24142002-12-16 13:33:51 +0000478}
479
480/* gtp_conf
481 * Remove signalling packet from retransmission queue.
482 * return 0 on success, EOF if packet was not found */
483
484int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100485 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
486{
jjako52c24142002-12-16 13:33:51 +0000487
Harald Weltebed35df2011-11-02 13:06:18 +0100488 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000489
Harald Weltebed35df2011-11-02 13:06:18 +0100490 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
491 seq = ntoh16(packet->gtp0.h.seq);
492 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
493 seq = ntoh16(packet->gtp1l.h.seq);
494 else {
495 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
496 "Unknown GTP packet version");
497 return EOF;
498 }
jjako08d331d2003-10-13 20:33:30 +0000499
Harald Weltebed35df2011-11-02 13:06:18 +0100500 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
501 gsn->err_seq++;
502 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
503 "Confirmation packet not found in queue");
504 return EOF;
505 }
jjako52c24142002-12-16 13:33:51 +0000506
Harald Weltebed35df2011-11-02 13:06:18 +0100507 return 0;
jjako52c24142002-12-16 13:33:51 +0000508}
509
Harald Weltebed35df2011-11-02 13:06:18 +0100510int gtp_retrans(struct gsn_t *gsn)
511{
512 /* Retransmit any outstanding packets */
513 /* Remove from queue if maxretrans exceeded */
514 time_t now;
515 struct qmsg_t *qmsg;
516 now = time(NULL);
517 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000518
Harald Welte95848ba2011-11-02 18:17:50 +0100519 /* get first element in queue, as long as the timeout of that
520 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100521 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
522 (qmsg->timeout <= now)) {
523 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100524 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100525 if (gsn->cb_conf)
526 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
527 queue_freemsg(gsn->queue_req, qmsg);
528 } else {
529 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
530 (struct sockaddr *)&qmsg->peer,
531 sizeof(struct sockaddr_in)) < 0) {
532 gsn->err_sendto++;
533 gtp_err(LOG_ERR, __FILE__, __LINE__,
534 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s",
535 gsn->fd0, (unsigned long)&qmsg->p,
536 qmsg->l, strerror(errno));
537 }
538 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100539 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100540 qmsg->retrans++;
541 }
542 }
jjako52c24142002-12-16 13:33:51 +0000543
Harald Weltebed35df2011-11-02 13:06:18 +0100544 /* Also clean up reply timeouts */
545 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
546 (qmsg->timeout < now)) {
547 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
548 queue_freemsg(gsn->queue_resp, qmsg);
549 }
jjako52c24142002-12-16 13:33:51 +0000550
Harald Weltebed35df2011-11-02 13:06:18 +0100551 return 0;
jjako52c24142002-12-16 13:33:51 +0000552}
553
Harald Weltebed35df2011-11-02 13:06:18 +0100554int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
555{
556 time_t now, later;
557 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000558
Harald Weltebed35df2011-11-02 13:06:18 +0100559 if (queue_getfirst(gsn->queue_req, &qmsg)) {
560 timeout->tv_sec = 10;
561 timeout->tv_usec = 0;
562 } else {
563 now = time(NULL);
564 later = qmsg->timeout;
565 timeout->tv_sec = later - now;
566 timeout->tv_usec = 0;
567 if (timeout->tv_sec < 0)
568 timeout->tv_sec = 0; /* No negative allowed */
569 if (timeout->tv_sec > 10)
570 timeout->tv_sec = 10; /* Max sleep for 10 sec */
571 }
572 return 0;
jjako52c24142002-12-16 13:33:51 +0000573}
574
Harald Weltebed35df2011-11-02 13:06:18 +0100575int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000576 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100577 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
578{
579 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000580
Harald Weltebed35df2011-11-02 13:06:18 +0100581 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
582 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
583 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100584 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100585 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
586 (packet->gtp0.h.type == GTP_ERROR)))
587 packet->gtp0.h.flow = hton16(pdp->flru);
588 else if (pdp)
589 packet->gtp0.h.flow = hton16(pdp->flrc);
590 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
591 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
592 packet->gtp1l.h.seq = hton16(seq);
593 if (pdp && (fd == gsn->fd1u))
594 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
595 else if (pdp)
596 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
597 } else {
598 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
599 return -1;
600 }
jjako08d331d2003-10-13 20:33:30 +0000601
Harald Weltebed35df2011-11-02 13:06:18 +0100602 if (fcntl(fd, F_SETFL, 0)) {
603 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
604 return -1;
605 }
jjako52c24142002-12-16 13:33:51 +0000606
Harald Weltebed35df2011-11-02 13:06:18 +0100607 if (sendto(fd, packet, len, 0,
608 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
609 gsn->err_sendto++;
610 gtp_err(LOG_ERR, __FILE__, __LINE__,
611 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
612 (unsigned long)&packet, len, strerror(errno));
613 return -1;
614 }
615
616 /* Use new queue structure */
617 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
618 gsn->err_queuefull++;
619 gtp_err(LOG_ERR, __FILE__, __LINE__,
620 "Retransmit queue is full");
621 } else {
622 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
623 qmsg->l = len;
624 qmsg->timeout = time(NULL) + 60; /* When to timeout */
625 qmsg->retrans = 0; /* No retransmissions so far */
626 qmsg->cbp = NULL;
627 qmsg->type = 0;
628 qmsg->fd = fd;
629 }
630 return 0;
jjako52c24142002-12-16 13:33:51 +0000631}
632
jjako2c381332003-10-21 19:09:53 +0000633int gtp_notification(struct gsn_t *gsn, int version,
634 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100635 struct sockaddr_in *peer, int fd, uint16_t seq)
636{
jjako2c381332003-10-21 19:09:53 +0000637
Harald Weltebed35df2011-11-02 13:06:18 +0100638 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000639
Harald Weltebed35df2011-11-02 13:06:18 +0100640 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000641
Harald Weltebed35df2011-11-02 13:06:18 +0100642 /* In GTP0 notifications are treated as replies. In GTP1 they
643 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000644
Harald Weltebed35df2011-11-02 13:06:18 +0100645 if (fd == gsn->fd1c)
646 addr.sin_port = htons(GTP1C_PORT);
647 else if (fd == gsn->fd1u)
648 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000649
Harald Weltebed35df2011-11-02 13:06:18 +0100650 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
651 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
652 packet->gtp0.h.seq = hton16(seq);
653 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
654 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
655 packet->gtp1l.h.seq = hton16(seq);
656 } else {
657 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
658 return -1;
659 }
660
661 if (fcntl(fd, F_SETFL, 0)) {
662 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
663 return -1;
664 }
665
666 if (sendto(fd, packet, len, 0,
667 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
668 gsn->err_sendto++;
669 gtp_err(LOG_ERR, __FILE__, __LINE__,
670 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
671 (unsigned long)&packet, len, strerror(errno));
672 return -1;
673 }
674 return 0;
jjako2c381332003-10-21 19:09:53 +0000675}
676
Harald Weltebed35df2011-11-02 13:06:18 +0100677int gtp_dublicate(struct gsn_t *gsn, int version,
678 struct sockaddr_in *peer, uint16_t seq)
679{
680 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000681
Harald Weltebed35df2011-11-02 13:06:18 +0100682 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
683 return EOF; /* Notfound */
684 }
jjakoa7cd2492003-04-11 09:40:12 +0000685
Harald Weltebed35df2011-11-02 13:06:18 +0100686 if (fcntl(qmsg->fd, F_SETFL, 0)) {
687 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
688 return -1;
689 }
690
691 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
692 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
693 gsn->err_sendto++;
694 gtp_err(LOG_ERR, __FILE__, __LINE__,
695 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s",
696 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
697 strerror(errno));
698 }
699 return 0;
jjako52c24142002-12-16 13:33:51 +0000700}
701
jjako52c24142002-12-16 13:33:51 +0000702/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100703static void log_restart(struct gsn_t *gsn)
704{
jjako52c24142002-12-16 13:33:51 +0000705 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200706 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000707 int counter = 0;
708 char filename[NAMESIZE];
709
Harald Weltebed35df2011-11-02 13:06:18 +0100710 filename[NAMESIZE - 1] = 0; /* No null term. guarantee by strncpy */
711 strncpy(filename, gsn->statedir, NAMESIZE - 1);
712 strncat(filename, RESTART_FILE, NAMESIZE - 1 - sizeof(RESTART_FILE));
jjako52c24142002-12-16 13:33:51 +0000713
714 i = umask(022);
715
716 /* We try to open file. On failure we will later try to create file */
717 if (!(f = fopen(filename, "r"))) {
jjako581c9f02003-10-22 11:28:20 +0000718
Harald Weltebed35df2011-11-02 13:06:18 +0100719 gtp_err(LOG_ERR, __FILE__, __LINE__,
720 "State information file (%s) not found. Creating new file.",
721 filename);
722 } else {
723 umask(i);
724 rc = fscanf(f, "%d", &counter);
725 if (rc != 1) {
726 gtp_err(LOG_ERR, __FILE__, __LINE__,
727 "fscanf failed to read counter value");
728 return;
729 }
730 if (fclose(f)) {
731 gtp_err(LOG_ERR, __FILE__, __LINE__,
732 "fclose failed: Error = %s", strerror(errno));
733 }
jjako52c24142002-12-16 13:33:51 +0000734 }
Harald Weltebed35df2011-11-02 13:06:18 +0100735
736 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000737 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100738
jjako52c24142002-12-16 13:33:51 +0000739 if (!(f = fopen(filename, "w"))) {
Harald Weltebed35df2011-11-02 13:06:18 +0100740 gtp_err(LOG_ERR, __FILE__, __LINE__,
741 "fopen(path=%s, mode=%s) failed: Error = %s", filename,
742 "w", strerror(errno));
743 return;
jjako52c24142002-12-16 13:33:51 +0000744 }
745
746 umask(i);
747 fprintf(f, "%d\n", gsn->restart_counter);
748 if (fclose(f)) {
Harald Weltebed35df2011-11-02 13:06:18 +0100749 gtp_err(LOG_ERR, __FILE__, __LINE__,
750 "fclose failed: Error = %s", strerror(errno));
751 return;
jjako52c24142002-12-16 13:33:51 +0000752 }
753}
754
jjako1db1c812003-07-06 20:53:57 +0000755int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100756 int mode)
jjako52c24142002-12-16 13:33:51 +0000757{
Harald Weltebed35df2011-11-02 13:06:18 +0100758 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000759
Harald Weltebed35df2011-11-02 13:06:18 +0100760 syslog(LOG_ERR, "GTP: gtp_newgsn() started");
jjako52c24142002-12-16 13:33:51 +0000761
Harald Weltebed35df2011-11-02 13:06:18 +0100762 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000763
Harald Weltebed35df2011-11-02 13:06:18 +0100764 (*gsn)->statedir = statedir;
765 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000766
Harald Weltebed35df2011-11-02 13:06:18 +0100767 /* Initialise sequence number */
768 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000769
Harald Weltebed35df2011-11-02 13:06:18 +0100770 /* Initialise request retransmit queue */
771 queue_new(&(*gsn)->queue_req);
772 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000773
Harald Weltebed35df2011-11-02 13:06:18 +0100774 /* Initialise pdp table */
775 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000776
Harald Weltebed35df2011-11-02 13:06:18 +0100777 /* Initialise call back functions */
778 (*gsn)->cb_create_context_ind = 0;
779 (*gsn)->cb_delete_context = 0;
780 (*gsn)->cb_unsup_ind = 0;
781 (*gsn)->cb_conf = 0;
782 (*gsn)->cb_data_ind = 0;
783
784 /* Store function parameters */
785 (*gsn)->gsnc = *listen;
786 (*gsn)->gsnu = *listen;
787 (*gsn)->mode = mode;
788
789 /* Create GTP version 0 socket */
790 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
791 (*gsn)->err_socket++;
792 gtp_err(LOG_ERR, __FILE__, __LINE__,
793 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
794 AF_INET, SOCK_DGRAM, 0, strerror(errno));
795 return -1;
796 }
797
798 memset(&addr, 0, sizeof(addr));
799 addr.sin_family = AF_INET;
800 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
801 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000802#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100803 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000804#endif
jjako08d331d2003-10-13 20:33:30 +0000805
Harald Weltebed35df2011-11-02 13:06:18 +0100806 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
807 (*gsn)->err_socket++;
808 gtp_err(LOG_ERR, __FILE__, __LINE__,
809 "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s",
810 (*gsn)->fd0, (unsigned long)&addr, sizeof(addr),
811 strerror(errno));
812 return -1;
813 }
jjako08d331d2003-10-13 20:33:30 +0000814
Harald Weltebed35df2011-11-02 13:06:18 +0100815 /* Create GTP version 1 control plane socket */
816 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
817 (*gsn)->err_socket++;
818 gtp_err(LOG_ERR, __FILE__, __LINE__,
819 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
820 AF_INET, SOCK_DGRAM, 0, strerror(errno));
821 return -1;
822 }
823
824 memset(&addr, 0, sizeof(addr));
825 addr.sin_family = AF_INET;
826 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
827 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000828#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100829 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000830#endif
jjako08d331d2003-10-13 20:33:30 +0000831
Harald Weltebed35df2011-11-02 13:06:18 +0100832 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
833 (*gsn)->err_socket++;
834 gtp_err(LOG_ERR, __FILE__, __LINE__,
835 "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
836 (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
837 strerror(errno));
838 return -1;
839 }
jjako08d331d2003-10-13 20:33:30 +0000840
Harald Weltebed35df2011-11-02 13:06:18 +0100841 /* Create GTP version 1 user plane socket */
842 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
843 (*gsn)->err_socket++;
844 gtp_err(LOG_ERR, __FILE__, __LINE__,
845 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
846 AF_INET, SOCK_DGRAM, 0, strerror(errno));
847 return -1;
848 }
849
850 memset(&addr, 0, sizeof(addr));
851 addr.sin_family = AF_INET;
852 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
853 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000854#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100855 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000856#endif
jjako52c24142002-12-16 13:33:51 +0000857
Harald Weltebed35df2011-11-02 13:06:18 +0100858 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
859 (*gsn)->err_socket++;
860 gtp_err(LOG_ERR, __FILE__, __LINE__,
861 "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
862 (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
863 strerror(errno));
864 return -1;
865 }
866
867 return 0;
jjako52c24142002-12-16 13:33:51 +0000868}
869
Harald Weltebed35df2011-11-02 13:06:18 +0100870int gtp_free(struct gsn_t *gsn)
871{
jjako52c24142002-12-16 13:33:51 +0000872
Harald Weltebed35df2011-11-02 13:06:18 +0100873 /* Clean up retransmit queues */
874 queue_free(gsn->queue_req);
875 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000876
Harald Weltebed35df2011-11-02 13:06:18 +0100877 close(gsn->fd0);
878 close(gsn->fd1c);
879 close(gsn->fd1u);
880
881 free(gsn);
882 return 0;
jjako52c24142002-12-16 13:33:51 +0000883}
884
885/* ***********************************************************
886 * Path management messages
887 * Messages: echo and version not supported.
888 * A path is connection between two UDP/IP endpoints
889 *
890 * A path is either using GTP0 or GTP1. A path can be
891 * established by any kind of GTP message??
892
893 * Which source port to use?
894 * GTP-C request destination port is 2123/3386
895 * GTP-U request destination port is 2152/3386
896 * T-PDU destination port is 2152/3386.
897 * For the above messages the source port is locally allocated.
898 * For response messages src=rx-dst and dst=rx-src.
899 * For simplicity we should probably use 2123+2152/3386 as
900 * src port even for the cases where src can be locally
901 * allocated. This also means that we have to listen only to
902 * the same ports.
903 * For response messages we need to be able to respond to
904 * the relevant src port even if it is locally allocated by
905 * the peer.
906 *
907 * The need for path management!
908 * We might need to keep a list of active paths. This might
909 * be in the form of remote IP address + UDP port numbers.
910 * (We will consider a path astablished if we have a context
911 * with the node in question)
912 *************************************************************/
913
914/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000915int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
916 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000917{
Harald Weltebed35df2011-11-02 13:06:18 +0100918 union gtp_packet packet;
919 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
920 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000921}
922
jjako08d331d2003-10-13 20:33:30 +0000923/* Send off an echo reply */
924int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100925 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000926{
Harald Weltebed35df2011-11-02 13:06:18 +0100927 union gtp_packet packet;
928 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
929 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
930 gsn->restart_counter);
931 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
932 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000933}
934
jjako52c24142002-12-16 13:33:51 +0000935/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100936int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
937 int fd, void *pack, unsigned len)
938{
jjako52c24142002-12-16 13:33:51 +0000939
Harald Weltebed35df2011-11-02 13:06:18 +0100940 /* Check if it was a dublicate request */
941 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
942 return 0;
jjako52c24142002-12-16 13:33:51 +0000943
Harald Weltebed35df2011-11-02 13:06:18 +0100944 /* Send off reply to request */
945 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000946}
947
948/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000949int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100950 void *pack, unsigned len)
951{
952 union gtpie_member *ie[GTPIE_SIZE];
953 unsigned char recovery;
954 void *cbp = NULL;
955 uint8_t type = 0;
956 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000957
Harald Weltebed35df2011-11-02 13:06:18 +0100958 /* Remove packet from queue */
959 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
960 return EOF;
jjako52c24142002-12-16 13:33:51 +0000961
Harald Weltebed35df2011-11-02 13:06:18 +0100962 /* Extract information elements into a pointer array */
963 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
964 gsn->invalid++;
965 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
966 "Invalid message format");
967 if (gsn->cb_conf)
968 gsn->cb_conf(type, EOF, NULL, cbp);
969 return EOF;
970 }
jjako52c24142002-12-16 13:33:51 +0000971
Harald Weltebed35df2011-11-02 13:06:18 +0100972 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
973 gsn->missing++;
974 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
975 "Missing mandatory field");
976 if (gsn->cb_conf)
977 gsn->cb_conf(type, EOF, NULL, cbp);
978 return EOF;
979 }
jjako52c24142002-12-16 13:33:51 +0000980
Harald Weltebed35df2011-11-02 13:06:18 +0100981 /* Echo reply packages does not have a cause information element */
982 /* Instead we return the recovery number in the callback function */
983 if (gsn->cb_conf)
984 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100985
Harald Weltebed35df2011-11-02 13:06:18 +0100986 if (gsn->cb_recovery)
987 gsn->cb_recovery(peer, recovery);
988
989 return 0;
jjako52c24142002-12-16 13:33:51 +0000990}
991
992/* Send off a Version Not Supported message */
993/* This message is somewhat special in that it actually is a
994 * response to some other message with unsupported GTP version
995 * For this reason it has parameters like a response, and does
996 * its own message transmission. No signalling queue is used
997 * The reply is sent to the peer IP and peer UDP. This means that
998 * the peer will be receiving a GTP0 message on a GTP1 port!
999 * In practice however this will never happen as a GTP0 GSN will
1000 * only listen to the GTP0 port, and therefore will never receive
1001 * anything else than GTP0 */
1002
jjako08d331d2003-10-13 20:33:30 +00001003int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1004 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00001005{
Harald Weltebed35df2011-11-02 13:06:18 +01001006 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001007
Harald Weltebed35df2011-11-02 13:06:18 +01001008 /* GTP 1 is the highest supported protocol */
1009 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1010 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001011}
1012
1013/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001014int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1015 void *pack, unsigned len)
1016{
jjako52c24142002-12-16 13:33:51 +00001017
Harald Weltebed35df2011-11-02 13:06:18 +01001018 if (gsn->cb_unsup_ind)
1019 gsn->cb_unsup_ind(peer);
1020
1021 return 0;
jjako52c24142002-12-16 13:33:51 +00001022}
1023
jjako2c381332003-10-21 19:09:53 +00001024/* Send off an Supported Extension Headers Notification */
1025int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1026 int fd, void *pack, unsigned len)
1027{
Harald Weltebed35df2011-11-02 13:06:18 +01001028 union gtp_packet packet;
1029 unsigned int length =
1030 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001033
Harald Weltebed35df2011-11-02 13:06:18 +01001034 if (version < 1)
1035 return 0;
jjako2c381332003-10-21 19:09:53 +00001036
Harald Weltebed35df2011-11-02 13:06:18 +01001037 /* We report back that we support only PDCP PDU headers */
1038 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1039 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001040
Harald Weltebed35df2011-11-02 13:06:18 +01001041 return gtp_notification(gsn, version, &packet, length,
1042 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001043}
1044
1045/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +01001046int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1047 void *pack, unsigned len)
1048{
jjako2c381332003-10-21 19:09:53 +00001049
Harald Weltebed35df2011-11-02 13:06:18 +01001050 if (gsn->cb_extheader_ind)
1051 gsn->cb_extheader_ind(peer);
1052
1053 return 0;
jjako2c381332003-10-21 19:09:53 +00001054}
1055
jjako52c24142002-12-16 13:33:51 +00001056/* ***********************************************************
1057 * Session management messages
1058 * Messages: create, update and delete PDP context
1059 *
1060 * Information storage
1061 * Information storage for each PDP context is defined in
1062 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1063 * PDP-address (IP address), sequence numbers, charging ID.
1064 * For the SGSN it also includes radio related mobility
1065 * information.
1066 *************************************************************/
1067
Harald Welte7b3347b2010-05-15 12:18:46 +02001068/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001069extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1070 void *cbp)
1071{
1072 union gtp_packet packet;
1073 unsigned int length =
1074 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1075 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 /* TODO: Secondary PDP Context Activation Procedure */
1078 /* In secondary activation procedure the PDP context is identified
1079 by tei in the header. The following fields are omitted: Selection
1080 mode, IMSI, MSISDN, End User Address, Access Point Name and
1081 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001082
Harald Weltebed35df2011-11-02 13:06:18 +01001083 if (pdp->secondary) {
1084 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
1085 gtp_err(LOG_ERR, __FILE__, __LINE__,
1086 "Unknown linked PDP context");
1087 return EOF;
1088 }
1089 }
jjako2c381332003-10-21 19:09:53 +00001090
Harald Weltebed35df2011-11-02 13:06:18 +01001091 if (pdp->version == 0) {
1092 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1093 sizeof(pdp->qos_req0), pdp->qos_req0);
1094 }
jjako52c24142002-12-16 13:33:51 +00001095
Harald Weltebed35df2011-11-02 13:06:18 +01001096 /* Section 7.7.2 */
1097 if (pdp->version == 1) {
1098 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1099 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1100 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1101 }
jjako52c24142002-12-16 13:33:51 +00001102
Harald Weltebed35df2011-11-02 13:06:18 +01001103 /* Section 7.7.3 Routing Area Information */
1104 if (pdp->rai_given == 1)
1105 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1106 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001107
Harald Weltebed35df2011-11-02 13:06:18 +01001108 /* Section 7.7.11 */
1109 if (pdp->norecovery_given == 0)
1110 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1111 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001112
Harald Weltebed35df2011-11-02 13:06:18 +01001113 /* Section 7.7.12 */
1114 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1115 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1116 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001117
Harald Weltebed35df2011-11-02 13:06:18 +01001118 if (pdp->version == 0) {
1119 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1120 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1121 }
jjako08d331d2003-10-13 20:33:30 +00001122
Harald Weltebed35df2011-11-02 13:06:18 +01001123 /* Section 7.7.13 */
1124 if (pdp->version == 1) {
1125 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1126 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001127
Harald Weltebed35df2011-11-02 13:06:18 +01001128 /* Section 7.7.14 */
1129 if (!pdp->teic_confirmed)
1130 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1131 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001132
Harald Weltebed35df2011-11-02 13:06:18 +01001133 /* Section 7.7.17 */
1134 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001135
Harald Weltebed35df2011-11-02 13:06:18 +01001136 /* Section 7.7.17 */
1137 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1138 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1139 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001140
Harald Weltebed35df2011-11-02 13:06:18 +01001141 /* Section 7.7.23 */
1142 if (pdp->cch_pdp) /* Only include charging if flags are set */
1143 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1144 pdp->cch_pdp);
1145 }
jjako9b4971d2004-05-27 20:30:19 +00001146
Harald Weltebed35df2011-11-02 13:06:18 +01001147 /* TODO
1148 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1149 pdp->traceref);
1150 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1151 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001152
Harald Weltebed35df2011-11-02 13:06:18 +01001153 /* Section 7.7.27 */
1154 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1155 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1156 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001157
Harald Weltebed35df2011-11-02 13:06:18 +01001158 /* Section 7.7.30 */
1159 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1160 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1161 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001162
Harald Weltebed35df2011-11-02 13:06:18 +01001163 /* Section 7.7.31 */
1164 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1165 if (pdp->pco_req.l)
1166 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1167 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001168
Harald Weltebed35df2011-11-02 13:06:18 +01001169 /* Section 7.7.32 */
1170 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1171 pdp->gsnlc.l, pdp->gsnlc.v);
1172 /* Section 7.7.32 */
1173 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1174 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001175
Harald Weltebed35df2011-11-02 13:06:18 +01001176 /* Section 7.7.33 */
1177 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1178 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1179 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001180
Harald Weltebed35df2011-11-02 13:06:18 +01001181 /* Section 7.7.34 */
1182 if (pdp->version == 1)
1183 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1184 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001185
Harald Weltebed35df2011-11-02 13:06:18 +01001186 /* Section 7.7.36 */
1187 if ((pdp->version == 1) && pdp->tft.l)
1188 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1189 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001190
Harald Weltebed35df2011-11-02 13:06:18 +01001191 /* Section 7.7.41 */
1192 if ((pdp->version == 1) && pdp->triggerid.l)
1193 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1194 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001195
Harald Weltebed35df2011-11-02 13:06:18 +01001196 /* Section 7.7.42 */
1197 if ((pdp->version == 1) && pdp->omcid.l)
1198 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1199 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001200
Harald Weltebed35df2011-11-02 13:06:18 +01001201 /* new R7 fields */
1202 if (pdp->rattype_given == 1)
1203 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1204 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001205
Harald Weltebed35df2011-11-02 13:06:18 +01001206 if (pdp->userloc_given == 1)
1207 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1208 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001209
Harald Weltebed35df2011-11-02 13:06:18 +01001210 if (pdp->mstz_given == 1)
1211 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1212 pdp->mstz.l, pdp->mstz.v);
1213
1214 if (pdp->imeisv_given == 1)
1215 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1216 pdp->imeisv.l, pdp->imeisv.v);
1217
1218 /* TODO hisaddr0 */
1219 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1220
1221 return 0;
jjako52c24142002-12-16 13:33:51 +00001222}
1223
jjako08d331d2003-10-13 20:33:30 +00001224/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001225int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1226{
jjako08d331d2003-10-13 20:33:30 +00001227
Harald Weltebed35df2011-11-02 13:06:18 +01001228 /* Now send off a reply to the peer */
1229 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1230
1231 if (cause != GTPCAUSE_ACC_REQ) {
1232 pdp_freepdp(pdp);
1233 }
1234
1235 return 0;
jjako08d331d2003-10-13 20:33:30 +00001236}
1237
1238/* API: Register create context indication callback */
1239int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001240 int (*cb_create_context_ind) (struct pdp_t *
1241 pdp))
jjako52c24142002-12-16 13:33:51 +00001242{
Harald Weltebed35df2011-11-02 13:06:18 +01001243 gsn->cb_create_context_ind = cb_create_context_ind;
1244 return 0;
jjako08d331d2003-10-13 20:33:30 +00001245}
1246
jjako08d331d2003-10-13 20:33:30 +00001247/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001248int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1249 uint8_t cause)
1250{
1251 union gtp_packet packet;
1252 unsigned int length =
1253 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001254
Harald Weltebed35df2011-11-02 13:06:18 +01001255 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001256
Harald Weltebed35df2011-11-02 13:06:18 +01001257 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001258
Harald Weltebed35df2011-11-02 13:06:18 +01001259 if (version == 0)
1260 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1261 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001262
Harald Weltebed35df2011-11-02 13:06:18 +01001263 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1264 pdp->reorder);
1265 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1266 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001267
Harald Weltebed35df2011-11-02 13:06:18 +01001268 if (version == 0) {
1269 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1270 pdp->fllu);
1271 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1272 pdp->fllc);
1273 }
jjako08d331d2003-10-13 20:33:30 +00001274
Harald Weltebed35df2011-11-02 13:06:18 +01001275 if (version == 1) {
1276 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1277 pdp->teid_own);
1278 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1279 pdp->teic_own);
1280 }
jjako08d331d2003-10-13 20:33:30 +00001281
Harald Weltebed35df2011-11-02 13:06:18 +01001282 /* TODO: We use teic_own as charging ID */
1283 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1284 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001285
Harald Weltebed35df2011-11-02 13:06:18 +01001286 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1287 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001288
Harald Weltebed35df2011-11-02 13:06:18 +01001289 if (pdp->pco_neg.l) { /* Optional PCO */
1290 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1291 pdp->pco_neg.l, pdp->pco_neg.v);
1292 }
jjako52c24142002-12-16 13:33:51 +00001293
Harald Weltebed35df2011-11-02 13:06:18 +01001294 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1295 pdp->gsnlc.l, pdp->gsnlc.v);
1296 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1297 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001298
Harald Weltebed35df2011-11-02 13:06:18 +01001299 if (version == 1)
1300 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1301 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001302
Harald Weltebed35df2011-11-02 13:06:18 +01001303 /* TODO: Charging gateway address */
1304 }
jjako52c24142002-12-16 13:33:51 +00001305
Harald Weltebed35df2011-11-02 13:06:18 +01001306 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1307 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001308}
1309
1310/* Handle Create PDP Context Request */
1311int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001312 struct sockaddr_in *peer, int fd,
1313 void *pack, unsigned len)
1314{
1315 struct pdp_t *pdp, *pdp_old;
1316 struct pdp_t pdp_buf;
1317 union gtpie_member *ie[GTPIE_SIZE];
1318 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001319
Harald Weltebed35df2011-11-02 13:06:18 +01001320 uint16_t seq = get_seq(pack);
1321 int hlen = get_hlen(pack);
1322 uint8_t linked_nsapi = 0;
1323 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001324
Harald Weltebed35df2011-11-02 13:06:18 +01001325 if (!gtp_dublicate(gsn, version, peer, seq))
1326 return 0;
jjako08d331d2003-10-13 20:33:30 +00001327
Harald Weltebed35df2011-11-02 13:06:18 +01001328 pdp = &pdp_buf;
1329 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001330
Harald Weltebed35df2011-11-02 13:06:18 +01001331 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001332 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1333
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001334 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001335 }
jjako52c24142002-12-16 13:33:51 +00001336
Harald Weltebed35df2011-11-02 13:06:18 +01001337 pdp->seq = seq;
1338 pdp->sa_peer = *peer;
1339 pdp->fd = fd;
1340 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001341
Harald Weltebed35df2011-11-02 13:06:18 +01001342 /* Decode information elements */
1343 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1344 gsn->invalid++;
1345 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1346 "Invalid message format");
1347 if (0 == version)
1348 return EOF;
1349 else
1350 return gtp_create_pdp_resp(gsn, version, pdp,
1351 GTPCAUSE_INVALID_MESSAGE);
1352 }
jjako52c24142002-12-16 13:33:51 +00001353
Harald Weltebed35df2011-11-02 13:06:18 +01001354 if (version == 1) {
1355 /* Linked NSAPI (conditional) */
1356 /* If included this is the Secondary PDP Context Activation Procedure */
1357 /* In secondary activation IMSI is not included, so the context must be */
1358 /* identified by the tei */
1359 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001360
Harald Weltebed35df2011-11-02 13:06:18 +01001361 /* Find the primary PDP context */
1362 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1363 gsn->incorrect++;
1364 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1365 pack, len,
1366 "Incorrect optional information field");
1367 return gtp_create_pdp_resp(gsn, version, pdp,
1368 GTPCAUSE_OPT_IE_INCORRECT);
1369 }
jjako2c381332003-10-21 19:09:53 +00001370
Harald Weltebed35df2011-11-02 13:06:18 +01001371 /* Check that the primary PDP context matches linked nsapi */
1372 if (linked_pdp->nsapi != linked_nsapi) {
1373 gsn->incorrect++;
1374 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1375 pack, len,
1376 "Incorrect optional information field");
1377 return gtp_create_pdp_resp(gsn, version, pdp,
1378 GTPCAUSE_OPT_IE_INCORRECT);
1379 }
jjako52c24142002-12-16 13:33:51 +00001380
Harald Weltebed35df2011-11-02 13:06:18 +01001381 /* Copy parameters from primary context */
1382 pdp->selmode = linked_pdp->selmode;
1383 pdp->imsi = linked_pdp->imsi;
1384 pdp->msisdn = linked_pdp->msisdn;
1385 pdp->eua = linked_pdp->eua;
1386 pdp->pco_req = linked_pdp->pco_req;
1387 pdp->apn_req = linked_pdp->apn_req;
1388 pdp->teic_gn = linked_pdp->teic_gn;
1389 pdp->secondary = 1;
1390 }
1391 }
1392 /* if (version == 1) */
1393 if (version == 0) {
1394 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1395 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1396 gsn->missing++;
1397 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1398 len, "Missing mandatory information field");
1399 return gtp_create_pdp_resp(gsn, version, pdp,
1400 GTPCAUSE_MAN_IE_MISSING);
1401 }
1402 }
jjako08d331d2003-10-13 20:33:30 +00001403
Harald Weltebed35df2011-11-02 13:06:18 +01001404 if ((version == 1) && (!linked_pdp)) {
1405 /* Not Secondary PDP Context Activation Procedure */
1406 /* IMSI (conditional) */
1407 if (gtpie_gettv0
1408 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1409 gsn->missing++;
1410 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1411 len, "Missing mandatory information field");
1412 return gtp_create_pdp_resp(gsn, version, pdp,
1413 GTPCAUSE_MAN_IE_MISSING);
1414 }
1415 }
jjako52c24142002-12-16 13:33:51 +00001416
Harald Weltebed35df2011-11-02 13:06:18 +01001417 /* Recovery (optional) */
1418 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1419 if (gsn->cb_recovery)
1420 gsn->cb_recovery(peer, recovery);
1421 }
jjako52c24142002-12-16 13:33:51 +00001422
Harald Weltebed35df2011-11-02 13:06:18 +01001423 /* Selection mode (conditional) */
1424 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1425 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1426 &pdp->selmode, sizeof(pdp->selmode))) {
1427 gsn->missing++;
1428 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1429 len, "Missing mandatory information field");
1430 return gtp_create_pdp_resp(gsn, version, pdp,
1431 GTPCAUSE_MAN_IE_MISSING);
1432 }
1433 }
jjako52c24142002-12-16 13:33:51 +00001434
Harald Weltebed35df2011-11-02 13:06:18 +01001435 if (version == 0) {
1436 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1437 gsn->missing++;
1438 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1439 len, "Missing mandatory information field");
1440 return gtp_create_pdp_resp(gsn, version, pdp,
1441 GTPCAUSE_MAN_IE_MISSING);
1442 }
jjako52c24142002-12-16 13:33:51 +00001443
Harald Weltebed35df2011-11-02 13:06:18 +01001444 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1445 gsn->missing++;
1446 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1447 len, "Missing mandatory information field");
1448 return gtp_create_pdp_resp(gsn, version, pdp,
1449 GTPCAUSE_MAN_IE_MISSING);
1450 }
1451 }
jjako08d331d2003-10-13 20:33:30 +00001452
Harald Weltebed35df2011-11-02 13:06:18 +01001453 if (version == 1) {
1454 /* TEID (mandatory) */
1455 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1456 gsn->missing++;
1457 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1458 len, "Missing mandatory information field");
1459 return gtp_create_pdp_resp(gsn, version, pdp,
1460 GTPCAUSE_MAN_IE_MISSING);
1461 }
jjako2c381332003-10-21 19:09:53 +00001462
Harald Weltebed35df2011-11-02 13:06:18 +01001463 /* TEIC (conditional) */
1464 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1465 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1466 gsn->missing++;
1467 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1468 pack, len,
1469 "Missing mandatory information field");
1470 return gtp_create_pdp_resp(gsn, version, pdp,
1471 GTPCAUSE_MAN_IE_MISSING);
1472 }
1473 }
jjako08d331d2003-10-13 20:33:30 +00001474
Harald Weltebed35df2011-11-02 13:06:18 +01001475 /* NSAPI (mandatory) */
1476 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1477 gsn->missing++;
1478 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1479 len, "Missing mandatory information field");
1480 return gtp_create_pdp_resp(gsn, version, pdp,
1481 GTPCAUSE_MAN_IE_MISSING);
1482 }
1483 }
jjako2e840a32003-01-28 16:05:18 +00001484
Harald Weltebed35df2011-11-02 13:06:18 +01001485 /* Charging Characteriatics (optional) */
1486 /* Trace reference (optional) */
1487 /* Trace type (optional) */
1488 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001489
Harald Weltebed35df2011-11-02 13:06:18 +01001490 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1491 /* End User Address (conditional) */
1492 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1493 &pdp->eua.v, sizeof(pdp->eua.v))) {
1494 gsn->missing++;
1495 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1496 len, "Missing mandatory information field");
1497 return gtp_create_pdp_resp(gsn, version, pdp,
1498 GTPCAUSE_MAN_IE_MISSING);
1499 }
jjako08d331d2003-10-13 20:33:30 +00001500
Harald Weltebed35df2011-11-02 13:06:18 +01001501 /* APN */
1502 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1503 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1504 gsn->missing++;
1505 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1506 len, "Missing mandatory information field");
1507 return gtp_create_pdp_resp(gsn, version, pdp,
1508 GTPCAUSE_MAN_IE_MISSING);
1509 }
jjako2c381332003-10-21 19:09:53 +00001510
Harald Weltebed35df2011-11-02 13:06:18 +01001511 /* Extract protocol configuration options (optional) */
1512 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1513 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1514 }
1515 }
jjako2c381332003-10-21 19:09:53 +00001516
Harald Weltebed35df2011-11-02 13:06:18 +01001517 /* SGSN address for signalling (mandatory) */
1518 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1519 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1520 gsn->missing++;
1521 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1522 "Missing mandatory information field");
1523 return gtp_create_pdp_resp(gsn, version, pdp,
1524 GTPCAUSE_MAN_IE_MISSING);
1525 }
jjako2e840a32003-01-28 16:05:18 +00001526
Harald Weltebed35df2011-11-02 13:06:18 +01001527 /* SGSN address for user traffic (mandatory) */
1528 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1529 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1530 gsn->missing++;
1531 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1532 "Missing mandatory information field");
1533 return gtp_create_pdp_resp(gsn, version, pdp,
1534 GTPCAUSE_MAN_IE_MISSING);
1535 }
jjako52c24142002-12-16 13:33:51 +00001536
Harald Weltebed35df2011-11-02 13:06:18 +01001537 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1538 /* MSISDN (conditional) */
1539 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1540 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1541 gsn->missing++;
1542 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1543 len, "Missing mandatory information field");
1544 return gtp_create_pdp_resp(gsn, version, pdp,
1545 GTPCAUSE_MAN_IE_MISSING);
1546 }
1547 }
jjako52c24142002-12-16 13:33:51 +00001548
Harald Weltebed35df2011-11-02 13:06:18 +01001549 if (version == 1) {
1550 /* QoS (mandatory) */
1551 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1552 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1553 gsn->missing++;
1554 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1555 len, "Missing mandatory information field");
1556 return gtp_create_pdp_resp(gsn, version, pdp,
1557 GTPCAUSE_MAN_IE_MISSING);
1558 }
1559
1560 /* TFT (conditional) */
1561 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1562 &pdp->tft.v, sizeof(pdp->tft.v))) {
1563 }
1564
1565 /* Trigger ID */
1566 /* OMC identity */
1567 }
1568
1569 /* Initialize our own IP addresses */
1570 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1571 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1572
1573 if (GTP_DEBUG)
1574 printf("gtp_create_pdp_ind: Before pdp_tidget\n");
1575
1576 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1577 /* Found old pdp with same tid. Now the voodoo begins! */
1578 /* 09.60 / 29.060 allows create on existing context to "steal" */
1579 /* the context which was allready established */
1580 /* We check that the APN, selection mode and MSISDN is the same */
1581 if (GTP_DEBUG)
1582 printf("gtp_create_pdp_ind: Old context found\n");
1583 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1584 &&
1585 (!memcmp
1586 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1587 && (pdp->selmode == pdp_old->selmode)
1588 && (pdp->msisdn.l == pdp_old->msisdn.l)
1589 &&
1590 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1591 {
1592 /* OK! We are dealing with the same APN. We will copy new
1593 * parameters to the old pdp and send off confirmation
1594 * We ignore the following information elements:
1595 * QoS: MS will get originally negotiated QoS.
1596 * End user address (EUA). MS will get old EUA anyway.
1597 * Protocol configuration option (PCO): Only application can verify */
1598
1599 if (GTP_DEBUG)
1600 printf
1601 ("gtp_create_pdp_ind: Old context found\n");
1602
1603 /* Copy remote flow label */
1604 pdp_old->flru = pdp->flru;
1605 pdp_old->flrc = pdp->flrc;
1606
1607 /* Copy remote tei */
1608 pdp_old->teid_gn = pdp->teid_gn;
1609 pdp_old->teic_gn = pdp->teic_gn;
1610
1611 /* Copy peer GSN address */
1612 pdp_old->gsnrc.l = pdp->gsnrc.l;
1613 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1614 pdp_old->gsnru.l = pdp->gsnru.l;
1615 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1616
1617 /* Copy request parameters */
1618 pdp_old->seq = pdp->seq;
1619 pdp_old->sa_peer = pdp->sa_peer;
1620 pdp_old->fd = pdp->fd = fd;
1621 pdp_old->version = pdp->version = version;
1622
1623 /* Switch to using the old pdp context */
1624 pdp = pdp_old;
1625
1626 /* Confirm to peer that things were "successful" */
1627 return gtp_create_pdp_resp(gsn, version, pdp,
1628 GTPCAUSE_ACC_REQ);
1629 } else { /* This is not the same PDP context. Delete the old one. */
1630
1631 if (GTP_DEBUG)
1632 printf
1633 ("gtp_create_pdp_ind: Deleting old context\n");
1634
1635 if (gsn->cb_delete_context)
1636 gsn->cb_delete_context(pdp_old);
1637 pdp_freepdp(pdp_old);
1638
1639 if (GTP_DEBUG)
1640 printf("gtp_create_pdp_ind: Deleted...\n");
1641 }
1642 }
1643
1644 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1645
1646 /* Callback function to validata login */
1647 if (gsn->cb_create_context_ind != 0)
1648 return gsn->cb_create_context_ind(pdp);
1649 else {
1650 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1651 "No create_context_ind callback defined");
1652 return gtp_create_pdp_resp(gsn, version, pdp,
1653 GTPCAUSE_NOT_SUPPORTED);
1654 }
jjako52c24142002-12-16 13:33:51 +00001655}
1656
jjako52c24142002-12-16 13:33:51 +00001657/* Handle Create PDP Context Response */
1658int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001659 struct sockaddr_in *peer, void *pack, unsigned len)
1660{
1661 struct pdp_t *pdp;
1662 union gtpie_member *ie[GTPIE_SIZE];
1663 uint8_t cause, recovery;
1664 void *cbp = NULL;
1665 uint8_t type = 0;
1666 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001667
Harald Weltebed35df2011-11-02 13:06:18 +01001668 /* Remove packet from queue */
1669 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1670 return EOF;
jjako52c24142002-12-16 13:33:51 +00001671
Harald Weltebed35df2011-11-02 13:06:18 +01001672 /* Find the context in question */
1673 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1674 gsn->err_unknownpdp++;
1675 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1676 "Unknown PDP context");
1677 if (gsn->cb_conf)
1678 gsn->cb_conf(type, EOF, NULL, cbp);
1679 return EOF;
1680 }
jjako2c381332003-10-21 19:09:53 +00001681
Harald Weltebed35df2011-11-02 13:06:18 +01001682 /* Register that we have received a valid teic from GGSN */
1683 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001684
Harald Weltebed35df2011-11-02 13:06:18 +01001685 /* Decode information elements */
1686 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1687 gsn->invalid++;
1688 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1689 "Invalid message format");
1690 if (gsn->cb_conf)
1691 gsn->cb_conf(type, EOF, pdp, cbp);
1692 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1693 pdp_freepdp(pdp); */
1694 return EOF;
1695 }
jjako52c24142002-12-16 13:33:51 +00001696
Harald Weltebed35df2011-11-02 13:06:18 +01001697 /* Extract cause value (mandatory) */
1698 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1699 gsn->missing++;
1700 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1701 "Missing mandatory information field");
1702 if (gsn->cb_conf)
1703 gsn->cb_conf(type, EOF, pdp, cbp);
1704 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1705 pdp_freepdp(pdp); */
1706 return EOF;
1707 }
jjako52c24142002-12-16 13:33:51 +00001708
Harald Weltebed35df2011-11-02 13:06:18 +01001709 /* Extract recovery (optional) */
1710 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1711 if (gsn->cb_recovery)
1712 gsn->cb_recovery(peer, recovery);
1713 }
jjako52c24142002-12-16 13:33:51 +00001714
Harald Weltebed35df2011-11-02 13:06:18 +01001715 /* Extract protocol configuration options (optional) */
1716 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1717 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1718 }
jjako52c24142002-12-16 13:33:51 +00001719
Harald Weltebed35df2011-11-02 13:06:18 +01001720 /* Check all conditional information elements */
1721 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001722
Harald Weltebed35df2011-11-02 13:06:18 +01001723 if (version == 0) {
1724 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1725 &pdp->qos_neg0,
1726 sizeof(pdp->qos_neg0))) {
1727 gsn->missing++;
1728 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1729 pack, len,
1730 "Missing conditional information field");
1731 if (gsn->cb_conf)
1732 gsn->cb_conf(type, EOF, pdp, cbp);
1733 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1734 pdp_freepdp(pdp); */
1735 return EOF;
1736 }
1737 }
jjako08d331d2003-10-13 20:33:30 +00001738
Harald Weltebed35df2011-11-02 13:06:18 +01001739 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1740 gsn->missing++;
1741 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1742 len,
1743 "Missing conditional information field");
1744 if (gsn->cb_conf)
1745 gsn->cb_conf(type, EOF, pdp, cbp);
1746 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1747 pdp_freepdp(pdp); */
1748 return EOF;
1749 }
jjako52c24142002-12-16 13:33:51 +00001750
Harald Weltebed35df2011-11-02 13:06:18 +01001751 if (version == 0) {
1752 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1753 gsn->missing++;
1754 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1755 pack, len,
1756 "Missing conditional information field");
1757 if (gsn->cb_conf)
1758 gsn->cb_conf(type, EOF, pdp, cbp);
1759 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1760 pdp_freepdp(pdp); */
1761 return EOF;
1762 }
jjako52c24142002-12-16 13:33:51 +00001763
Harald Weltebed35df2011-11-02 13:06:18 +01001764 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1765 gsn->missing++;
1766 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1767 pack, len,
1768 "Missing conditional information field");
1769 if (gsn->cb_conf)
1770 gsn->cb_conf(type, EOF, pdp, cbp);
1771 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1772 pdp_freepdp(pdp); */
1773 return EOF;
1774 }
1775 }
1776
1777 if (version == 1) {
1778 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1779 gsn->missing++;
1780 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1781 pack, len,
1782 "Missing conditional information field");
1783 if (gsn->cb_conf)
1784 gsn->cb_conf(type, EOF, pdp, cbp);
1785 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1786 pdp_freepdp(pdp); */
1787 return EOF;
1788 }
1789
1790 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1791 gsn->missing++;
1792 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1793 pack, len,
1794 "Missing conditional information field");
1795 if (gsn->cb_conf)
1796 gsn->cb_conf(type, EOF, pdp, cbp);
1797 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1798 pdp_freepdp(pdp); */
1799 return EOF;
1800 }
1801 }
1802
1803 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1804 gsn->missing++;
1805 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1806 len,
1807 "Missing conditional information field");
1808 if (gsn->cb_conf)
1809 gsn->cb_conf(type, EOF, pdp, cbp);
1810 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1811 pdp_freepdp(pdp); */
1812 }
1813
1814 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1815 &pdp->eua.v, sizeof(pdp->eua.v))) {
1816 gsn->missing++;
1817 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1818 len,
1819 "Missing conditional information field");
1820 if (gsn->cb_conf)
1821 gsn->cb_conf(type, EOF, pdp, cbp);
1822 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1823 pdp_freepdp(pdp); */
1824 return EOF;
1825 }
1826
1827 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1828 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1829 gsn->missing++;
1830 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1831 len,
1832 "Missing conditional information field");
1833 if (gsn->cb_conf)
1834 gsn->cb_conf(type, EOF, pdp, cbp);
1835 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1836 pdp_freepdp(pdp); */
1837 return EOF;
1838 }
1839
1840 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1841 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1842 gsn->missing++;
1843 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
1844 len,
1845 "Missing conditional information field");
1846 if (gsn->cb_conf)
1847 gsn->cb_conf(type, EOF, pdp, cbp);
1848 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1849 pdp_freepdp(pdp); */
1850 return EOF;
1851 }
1852
1853 if (version == 1) {
1854 if (gtpie_gettlv
1855 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1856 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1857 gsn->missing++;
1858 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
1859 pack, len,
1860 "Missing conditional information field");
1861 if (gsn->cb_conf)
1862 gsn->cb_conf(type, EOF, pdp, cbp);
1863 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1864 pdp_freepdp(pdp); */
1865 return EOF;
1866 }
1867 }
1868
1869 }
1870
1871 if (gsn->cb_conf)
1872 gsn->cb_conf(type, cause, pdp, cbp);
1873
1874 return 0;
jjako52c24142002-12-16 13:33:51 +00001875}
1876
jjako08d331d2003-10-13 20:33:30 +00001877/* API: Send Update PDP Context Request */
1878int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001879 struct in_addr *inetaddr)
1880{
1881 union gtp_packet packet;
1882 unsigned int length =
1883 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001884
Harald Weltebed35df2011-11-02 13:06:18 +01001885 if (pdp->version == 0)
1886 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1887 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001888
Harald Weltebed35df2011-11-02 13:06:18 +01001889 /* Include IMSI if updating with unknown teic_gn */
1890 if ((pdp->version == 1) && (!pdp->teic_gn))
1891 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1892 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1893
1894 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1895 gsn->restart_counter);
1896
1897 if (pdp->version == 0) {
1898 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1899 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1900 }
1901
1902 if (pdp->version == 1) {
1903 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1904 pdp->teid_own);
1905
1906 if (!pdp->teic_confirmed)
1907 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1908 pdp->teic_own);
1909 }
1910
1911 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1912
1913 /* TODO
1914 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1915 pdp->traceref);
1916 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1917 pdp->tracetype); */
1918
1919 /* TODO if ggsn update message
1920 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1921 pdp->eua.l, pdp->eua.v);
1922 */
1923
1924 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1925 pdp->gsnlc.l, pdp->gsnlc.v);
1926 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1927 pdp->gsnlu.l, pdp->gsnlu.v);
1928
1929 if (pdp->version == 1)
1930 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1931 pdp->qos_req.l, pdp->qos_req.v);
1932
1933 if ((pdp->version == 1) && pdp->tft.l)
1934 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1935 pdp->tft.l, pdp->tft.v);
1936
1937 if ((pdp->version == 1) && pdp->triggerid.l)
1938 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1939 pdp->triggerid.l, pdp->triggerid.v);
1940
1941 if ((pdp->version == 1) && pdp->omcid.l)
1942 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1943 pdp->omcid.l, pdp->omcid.v);
1944
1945 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1946
1947 return 0;
jjako52c24142002-12-16 13:33:51 +00001948}
1949
jjako08d331d2003-10-13 20:33:30 +00001950/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001951int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1952 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001953 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001954 struct pdp_t *pdp, uint8_t cause)
1955{
jjako08d331d2003-10-13 20:33:30 +00001956
Harald Weltebed35df2011-11-02 13:06:18 +01001957 union gtp_packet packet;
1958 unsigned int length =
1959 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001960
Harald Weltebed35df2011-11-02 13:06:18 +01001961 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001962
Harald Weltebed35df2011-11-02 13:06:18 +01001963 if (cause == GTPCAUSE_ACC_REQ) {
1964
1965 if (version == 0)
1966 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1967 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1968
1969 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1970 gsn->restart_counter);
1971
1972 if (version == 0) {
1973 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1974 pdp->fllu);
1975 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1976 pdp->fllc);
1977 }
1978
1979 if (version == 1) {
1980 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1981 pdp->teid_own);
1982
1983 if (!pdp->teic_confirmed)
1984 gtpie_tv4(&packet, &length, GTP_MAX,
1985 GTPIE_TEI_C, pdp->teic_own);
1986 }
1987
1988 /* TODO we use teid_own as charging ID address */
1989 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1990 pdp->teid_own);
1991
1992 /* If ggsn
1993 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1994 pdp->eua.l, pdp->eua.v); */
1995
1996 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1997 pdp->gsnlc.l, pdp->gsnlc.v);
1998 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1999 pdp->gsnlu.l, pdp->gsnlu.v);
2000
2001 if (version == 1)
2002 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
2003 pdp->qos_neg.l, pdp->qos_neg.v);
2004
2005 /* TODO: Charging gateway address */
2006 }
2007
2008 return gtp_resp(version, gsn, pdp, &packet, length, peer,
2009 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00002010}
2011
jjako52c24142002-12-16 13:33:51 +00002012/* Handle Update PDP Context Request */
2013int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002014 struct sockaddr_in *peer, int fd,
2015 void *pack, unsigned len)
2016{
2017 struct pdp_t *pdp;
2018 struct pdp_t pdp_backup;
2019 union gtpie_member *ie[GTPIE_SIZE];
2020 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002021
Harald Weltebed35df2011-11-02 13:06:18 +01002022 uint16_t seq = get_seq(pack);
2023 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002024
Harald Weltebed35df2011-11-02 13:06:18 +01002025 uint64_t imsi;
2026 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002027
Harald Weltebed35df2011-11-02 13:06:18 +01002028 /* Is this a dublicate ? */
2029 if (!gtp_dublicate(gsn, version, peer, seq)) {
2030 return 0; /* We allready send of response once */
2031 }
jjako08d331d2003-10-13 20:33:30 +00002032
Harald Weltebed35df2011-11-02 13:06:18 +01002033 /* Decode information elements */
2034 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2035 gsn->invalid++;
2036 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2037 "Invalid message format");
2038 if (0 == version)
2039 return EOF;
2040 else
2041 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2042 len, NULL,
2043 GTPCAUSE_INVALID_MESSAGE);
2044 }
jjako08d331d2003-10-13 20:33:30 +00002045
Harald Weltebed35df2011-11-02 13:06:18 +01002046 /* Finding PDP: */
2047 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2048 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2049 /* we have to use the tunnel endpoint identifier */
2050 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002051 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2052
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002053 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002054
Harald Weltebed35df2011-11-02 13:06:18 +01002055 /* Find the context in question */
2056 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2057 gsn->err_unknownpdp++;
2058 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2059 len, "Unknown PDP context");
2060 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2061 len, NULL,
2062 GTPCAUSE_NON_EXIST);
2063 }
2064 } else if (version == 1) {
2065 /* NSAPI (mandatory) */
2066 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2067 gsn->missing++;
2068 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2069 len, "Missing mandatory information field");
2070 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2071 len, NULL,
2072 GTPCAUSE_MAN_IE_MISSING);
2073 }
jjako08d331d2003-10-13 20:33:30 +00002074
Harald Weltebed35df2011-11-02 13:06:18 +01002075 /* IMSI (conditional) */
2076 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2077 /* Find the context in question */
2078 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2079 gsn->err_unknownpdp++;
2080 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
2081 pack, len, "Unknown PDP context");
2082 return gtp_update_pdp_resp(gsn, version, peer,
2083 fd, pack, len, NULL,
2084 GTPCAUSE_NON_EXIST);
2085 }
2086 } else {
2087 /* Find the context in question */
2088 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2089 gsn->err_unknownpdp++;
2090 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
2091 pack, len, "Unknown PDP context");
2092 return gtp_update_pdp_resp(gsn, version, peer,
2093 fd, pack, len, NULL,
2094 GTPCAUSE_NON_EXIST);
2095 }
2096 }
2097 } else {
2098 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
2099 return EOF;
2100 }
jjako08d331d2003-10-13 20:33:30 +00002101
Harald Weltebed35df2011-11-02 13:06:18 +01002102 /* Make a backup copy in case anything is wrong */
2103 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002104
Harald Weltebed35df2011-11-02 13:06:18 +01002105 if (version == 0) {
2106 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2107 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2108 gsn->missing++;
2109 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2110 len, "Missing mandatory information field");
2111 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2112 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2113 len, pdp,
2114 GTPCAUSE_MAN_IE_MISSING);
2115 }
2116 }
jjako52c24142002-12-16 13:33:51 +00002117
Harald Weltebed35df2011-11-02 13:06:18 +01002118 /* Recovery (optional) */
2119 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2120 if (gsn->cb_recovery)
2121 gsn->cb_recovery(peer, recovery);
2122 }
jjako08d331d2003-10-13 20:33:30 +00002123
Harald Weltebed35df2011-11-02 13:06:18 +01002124 if (version == 0) {
2125 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2126 gsn->missing++;
2127 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2128 len, "Missing mandatory information field");
2129 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2130 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2131 len, pdp,
2132 GTPCAUSE_MAN_IE_MISSING);
2133 }
jjako52c24142002-12-16 13:33:51 +00002134
Harald Weltebed35df2011-11-02 13:06:18 +01002135 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2136 gsn->missing++;
2137 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2138 len, "Missing mandatory information field");
2139 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2140 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2141 len, pdp,
2142 GTPCAUSE_MAN_IE_MISSING);
2143 }
2144 }
jjako52c24142002-12-16 13:33:51 +00002145
Harald Weltebed35df2011-11-02 13:06:18 +01002146 if (version == 1) {
2147 /* TEID (mandatory) */
2148 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2149 gsn->missing++;
2150 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2151 len, "Missing mandatory information field");
2152 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2153 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2154 len, pdp,
2155 GTPCAUSE_MAN_IE_MISSING);
2156 }
jjako52c24142002-12-16 13:33:51 +00002157
Harald Weltebed35df2011-11-02 13:06:18 +01002158 /* TEIC (conditional) */
2159 /* If TEIC is not included it means that we have allready received it */
2160 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2161 /* all updated contexts, or only for one of the linked contexts */
2162 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2163
2164 /* NSAPI (mandatory) */
2165 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2166 gsn->missing++;
2167 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2168 len, "Missing mandatory information field");
2169 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2170 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2171 len, pdp,
2172 GTPCAUSE_MAN_IE_MISSING);
2173 }
2174 }
2175
2176 /* Trace reference (optional) */
2177 /* Trace type (optional) */
2178
2179 /* End User Address (conditional) TODO: GGSN Initiated
2180 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2181 &pdp->eua.v, sizeof(pdp->eua.v))) {
2182 gsn->missing++;
2183 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2184 "Missing mandatory information field");
2185 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2186 return gtp_update_pdp_resp(gsn, version, pdp,
2187 GTPCAUSE_MAN_IE_MISSING);
2188 } */
2189
2190 /* SGSN address for signalling (mandatory) */
2191 /* It is weird that this is mandatory when TEIC is conditional */
2192 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2193 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2194 gsn->missing++;
2195 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2196 "Missing mandatory information field");
2197 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2198 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2199 pdp, GTPCAUSE_MAN_IE_MISSING);
2200 }
2201
2202 /* SGSN address for user traffic (mandatory) */
2203 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2204 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2205 gsn->missing++;
2206 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2207 "Missing mandatory information field");
2208 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2209 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2210 pdp, GTPCAUSE_MAN_IE_MISSING);
2211 }
2212
2213 if (version == 1) {
2214 /* QoS (mandatory) */
2215 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2216 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2217 gsn->missing++;
2218 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2219 len, "Missing mandatory information field");
2220 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2221 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2222 len, pdp,
2223 GTPCAUSE_MAN_IE_MISSING);
2224 }
2225
2226 /* TFT (conditional) */
2227 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2228 &pdp->tft.v, sizeof(pdp->tft.v))) {
2229 }
2230
2231 /* OMC identity */
2232 }
2233
2234 /* Confirm to peer that things were "successful" */
2235 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2236 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002237}
2238
jjako52c24142002-12-16 13:33:51 +00002239/* Handle Update PDP Context Response */
2240int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002241 struct sockaddr_in *peer, void *pack, unsigned len)
2242{
2243 struct pdp_t *pdp;
2244 union gtpie_member *ie[GTPIE_SIZE];
2245 uint8_t cause, recovery;
2246 void *cbp = NULL;
2247 uint8_t type = 0;
jjako52c24142002-12-16 13:33:51 +00002248
Harald Weltebed35df2011-11-02 13:06:18 +01002249 /* Remove packet from queue */
2250 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2251 return EOF;
jjako52c24142002-12-16 13:33:51 +00002252
Harald Weltebed35df2011-11-02 13:06:18 +01002253 /* Find the context in question */
2254 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2255 gsn->err_unknownpdp++;
2256 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2257 "Unknown PDP context");
2258 if (gsn->cb_conf)
2259 gsn->cb_conf(type, cause, NULL, cbp);
2260 return EOF;
2261 }
jjako2c381332003-10-21 19:09:53 +00002262
Harald Weltebed35df2011-11-02 13:06:18 +01002263 /* Register that we have received a valid teic from GGSN */
2264 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002265
Harald Weltebed35df2011-11-02 13:06:18 +01002266 /* Decode information elements */
2267 if (gtpie_decaps
2268 (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
2269 gsn->invalid++;
2270 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2271 "Invalid message format");
2272 if (gsn->cb_conf)
2273 gsn->cb_conf(type, EOF, pdp, cbp);
2274 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2275 pdp_freepdp(pdp); */
2276 return EOF;
2277 }
jjako52c24142002-12-16 13:33:51 +00002278
Harald Weltebed35df2011-11-02 13:06:18 +01002279 /* Extract cause value (mandatory) */
2280 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2281 gsn->missing++;
2282 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2283 "Missing mandatory information field");
2284 if (gsn->cb_conf)
2285 gsn->cb_conf(type, EOF, pdp, cbp);
2286 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2287 pdp_freepdp(pdp); */
2288 return EOF;
2289 }
jjako52c24142002-12-16 13:33:51 +00002290
Harald Weltebed35df2011-11-02 13:06:18 +01002291 /* Extract recovery (optional) */
2292 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2293 if (gsn->cb_recovery)
2294 gsn->cb_recovery(peer, recovery);
2295 }
2296
2297 /* Check all conditional information elements */
2298 if (GTPCAUSE_ACC_REQ != cause) {
2299 if (gsn->cb_conf)
2300 gsn->cb_conf(type, cause, pdp, cbp);
2301 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2302 pdp_freepdp(pdp); */
2303 return 0;
2304 } else {
2305 /* Check for missing conditionary information elements */
2306 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2307 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2308 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2309 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2310 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2311 gtpie_exist(ie, GTPIE_EUA, 0) &&
2312 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2313 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2314 gsn->missing++;
2315 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2316 len,
2317 "Missing conditional information field");
2318 if (gsn->cb_conf)
2319 gsn->cb_conf(type, EOF, pdp, cbp);
2320 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2321 pdp_freepdp(pdp); */
2322 return EOF;
2323 }
2324
2325 /* Update pdp with new values */
2326 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2327 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2328 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2329 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2330 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2331 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2332 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2333 &pdp->eua.v, sizeof(pdp->eua.v));
2334 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2335 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2336 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2337 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2338
2339 if (gsn->cb_conf)
2340 gsn->cb_conf(type, cause, pdp, cbp);
2341 return 0; /* Succes */
2342 }
jjako52c24142002-12-16 13:33:51 +00002343}
2344
jjako08d331d2003-10-13 20:33:30 +00002345/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002346int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002347 int teardown)
2348{
2349 union gtp_packet packet;
2350 unsigned int length =
2351 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2352 struct in_addr addr;
2353 struct pdp_t *linked_pdp;
2354 struct pdp_t *secondary_pdp;
2355 int n;
2356 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002357
Harald Weltebed35df2011-11-02 13:06:18 +01002358 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2359 gsn->err_address++;
2360 gtp_err(LOG_ERR, __FILE__, __LINE__,
2361 "GSN address conversion failed");
2362 return EOF;
jjako2c381332003-10-21 19:09:53 +00002363 }
jjako2c381332003-10-21 19:09:53 +00002364
Harald Weltebed35df2011-11-02 13:06:18 +01002365 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2366 gtp_err(LOG_ERR, __FILE__, __LINE__,
2367 "Unknown linked PDP context");
2368 return EOF;
2369 }
2370
2371 if (!teardown) {
2372 for (n = 0; n < PDP_MAXNSAPI; n++)
2373 if (linked_pdp->secondary_tei[n])
2374 count++;
2375 if (count <= 1) {
2376 gtp_err(LOG_ERR, __FILE__, __LINE__,
2377 "Must use teardown for last context");
2378 return EOF;
2379 }
2380 }
2381
2382 if (pdp->version == 1) {
2383 if (teardown)
2384 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2385 0xff);
2386
2387 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2388 }
2389
2390 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2391
2392 if (teardown) { /* Remove all contexts */
2393 for (n = 0; n < PDP_MAXNSAPI; n++) {
2394 if (linked_pdp->secondary_tei[n]) {
2395 if (pdp_getgtp1
2396 (&secondary_pdp,
2397 linked_pdp->secondary_tei[n])) {
2398 gtp_err(LOG_ERR, __FILE__, __LINE__,
2399 "Unknown secondary PDP context");
2400 return EOF;
2401 }
2402 if (linked_pdp != secondary_pdp) {
2403 if (gsn->cb_delete_context)
2404 gsn->cb_delete_context
2405 (secondary_pdp);
2406 pdp_freepdp(secondary_pdp);
2407 }
2408 }
2409 }
2410 if (gsn->cb_delete_context)
2411 gsn->cb_delete_context(linked_pdp);
2412 pdp_freepdp(linked_pdp);
2413 } else {
2414 if (gsn->cb_delete_context)
2415 gsn->cb_delete_context(pdp);
2416 if (pdp == linked_pdp) {
2417 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2418 linked_pdp->nodata = 1;
2419 } else
2420 pdp_freepdp(pdp);
2421 }
2422
2423 return 0;
jjako2c381332003-10-21 19:09:53 +00002424}
jjako08d331d2003-10-13 20:33:30 +00002425
jjako52c24142002-12-16 13:33:51 +00002426/* Send Delete PDP Context Response */
2427int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002428 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002429 void *pack, unsigned len,
2430 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002431 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002432{
Harald Weltebed35df2011-11-02 13:06:18 +01002433 union gtp_packet packet;
2434 struct pdp_t *secondary_pdp;
2435 unsigned int length =
2436 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2437 int n;
jjako52c24142002-12-16 13:33:51 +00002438
Harald Weltebed35df2011-11-02 13:06:18 +01002439 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002440
Harald Weltebed35df2011-11-02 13:06:18 +01002441 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2442 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002443
Harald Weltebed35df2011-11-02 13:06:18 +01002444 if (cause == GTPCAUSE_ACC_REQ) {
2445 if ((teardown) || (version == 0)) { /* Remove all contexts */
2446 for (n = 0; n < PDP_MAXNSAPI; n++) {
2447 if (linked_pdp->secondary_tei[n]) {
2448 if (pdp_getgtp1
2449 (&secondary_pdp,
2450 linked_pdp->secondary_tei[n])) {
2451 gtp_err(LOG_ERR, __FILE__,
2452 __LINE__,
2453 "Unknown secondary PDP context");
2454 return EOF;
2455 }
2456 if (linked_pdp != secondary_pdp) {
2457 if (gsn->cb_delete_context)
2458 gsn->cb_delete_context
2459 (secondary_pdp);
2460 pdp_freepdp(secondary_pdp);
2461 }
2462 }
2463 }
2464 if (gsn->cb_delete_context)
2465 gsn->cb_delete_context(linked_pdp);
2466 pdp_freepdp(linked_pdp);
2467 } else { /* Remove only current context */
2468 if (gsn->cb_delete_context)
2469 gsn->cb_delete_context(pdp);
2470 if (pdp == linked_pdp) {
2471 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2472 0;
2473 linked_pdp->nodata = 1;
2474 } else
2475 pdp_freepdp(pdp);
2476 }
jjako2c381332003-10-21 19:09:53 +00002477 }
Harald Weltebed35df2011-11-02 13:06:18 +01002478 /* if (cause == GTPCAUSE_ACC_REQ) */
2479 return 0;
jjako52c24142002-12-16 13:33:51 +00002480}
2481
2482/* Handle Delete PDP Context Request */
2483int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002484 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002485 void *pack, unsigned len)
2486{
2487 struct pdp_t *pdp = NULL;
2488 struct pdp_t *linked_pdp = NULL;
2489 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002490
Harald Weltebed35df2011-11-02 13:06:18 +01002491 uint16_t seq = get_seq(pack);
2492 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002493
Harald Weltebed35df2011-11-02 13:06:18 +01002494 uint8_t nsapi;
2495 uint8_t teardown = 0;
2496 int n;
2497 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002498
Harald Weltebed35df2011-11-02 13:06:18 +01002499 /* Is this a dublicate ? */
2500 if (!gtp_dublicate(gsn, version, peer, seq)) {
2501 return 0; /* We allready send off response once */
2502 }
jjako2c381332003-10-21 19:09:53 +00002503
Harald Weltebed35df2011-11-02 13:06:18 +01002504 /* Find the linked context in question */
2505 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2506 gsn->err_unknownpdp++;
2507 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2508 "Unknown PDP context");
2509 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2510 NULL, NULL, GTPCAUSE_NON_EXIST,
2511 teardown);
2512 }
jjako2c381332003-10-21 19:09:53 +00002513
Harald Weltebed35df2011-11-02 13:06:18 +01002514 /* If version 0 this is also the secondary context */
2515 if (version == 0)
2516 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002517
Harald Weltebed35df2011-11-02 13:06:18 +01002518 /* Decode information elements */
2519 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2520 gsn->invalid++;
2521 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2522 "Invalid message format");
2523 if (0 == version)
2524 return EOF;
2525 else
2526 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2527 len, NULL, NULL,
2528 GTPCAUSE_INVALID_MESSAGE,
2529 teardown);
2530 }
2531
2532 if (version == 1) {
2533 /* NSAPI (mandatory) */
2534 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2535 gsn->missing++;
2536 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2537 len, "Missing mandatory information field");
2538 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2539 len, NULL, NULL,
2540 GTPCAUSE_MAN_IE_MISSING,
2541 teardown);
2542 }
2543
2544 /* Find the context in question */
2545 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2546 gsn->err_unknownpdp++;
2547 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2548 len, "Unknown PDP context");
2549 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2550 len, NULL, NULL,
2551 GTPCAUSE_NON_EXIST,
2552 teardown);
2553 }
2554
2555 /* Teardown (conditional) */
2556 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2557
2558 if (!teardown) {
2559 for (n = 0; n < PDP_MAXNSAPI; n++)
2560 if (linked_pdp->secondary_tei[n])
2561 count++;
2562 if (count <= 1) {
2563 return 0; /* 29.060 7.3.5 Ignore message */
2564 }
2565 }
2566 }
2567
2568 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2569 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002570}
2571
jjako52c24142002-12-16 13:33:51 +00002572/* Handle Delete PDP Context Response */
2573int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002574 struct sockaddr_in *peer, void *pack, unsigned len)
2575{
2576 union gtpie_member *ie[GTPIE_SIZE];
2577 uint8_t cause;
2578 void *cbp = NULL;
2579 uint8_t type = 0;
2580 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002581
Harald Weltebed35df2011-11-02 13:06:18 +01002582 /* Remove packet from queue */
2583 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2584 return EOF;
jjako52c24142002-12-16 13:33:51 +00002585
Harald Weltebed35df2011-11-02 13:06:18 +01002586 /* Decode information elements */
2587 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2588 gsn->invalid++;
2589 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2590 "Invalid message format");
2591 if (gsn->cb_conf)
2592 gsn->cb_conf(type, EOF, NULL, cbp);
2593 return EOF;
2594 }
2595
2596 /* Extract cause value (mandatory) */
2597 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2598 gsn->missing++;
2599 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2600 "Missing mandatory information field");
2601 if (gsn->cb_conf)
2602 gsn->cb_conf(type, EOF, NULL, cbp);
2603 return EOF;
2604 }
2605
2606 /* Check the cause value (again) */
2607 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2608 gsn->err_cause++;
2609 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2610 "Unexpected cause value received: %d", cause);
2611 if (gsn->cb_conf)
2612 gsn->cb_conf(type, cause, NULL, cbp);
2613 return EOF;
2614 }
2615
2616 /* Callback function to notify application */
2617 if (gsn->cb_conf)
2618 gsn->cb_conf(type, cause, NULL, cbp);
2619
2620 return 0;
jjako52c24142002-12-16 13:33:51 +00002621}
2622
2623/* Send Error Indication (response to a GPDU message */
2624int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002625 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002626 void *pack, unsigned len)
2627{
Harald Weltebed35df2011-11-02 13:06:18 +01002628 union gtp_packet packet;
2629 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2630
2631 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2632 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002633}
2634
2635/* Handle Error Indication */
2636int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002637 struct sockaddr_in *peer, void *pack, unsigned len)
2638{
2639 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002640
Harald Weltebed35df2011-11-02 13:06:18 +01002641 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002642 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002643 gsn->err_unknownpdp++;
2644 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2645 "Unknown PDP context");
2646 return EOF;
2647 }
jjako52c24142002-12-16 13:33:51 +00002648
Harald Weltebed35df2011-11-02 13:06:18 +01002649 gsn->err_unknownpdp++; /* TODO: Change counter */
2650 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2651 "Received Error Indication");
2652
2653 if (gsn->cb_delete_context)
2654 gsn->cb_delete_context(pdp);
2655 pdp_freepdp(pdp);
2656 return 0;
jjako52c24142002-12-16 13:33:51 +00002657}
2658
2659int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002660 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2661{
jjako08d331d2003-10-13 20:33:30 +00002662
Harald Weltebed35df2011-11-02 13:06:18 +01002663 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002664
Harald Weltebed35df2011-11-02 13:06:18 +01002665 /* Need to include code to verify packet src and dest addresses */
2666 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002667
Harald Weltebed35df2011-11-02 13:06:18 +01002668 if (version == 0) {
2669 if (pdp_getgtp0
2670 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2671 gsn->err_unknownpdp++;
2672 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2673 len, "Unknown PDP context");
2674 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2675 len);
2676 }
2677 hlen = GTP0_HEADER_SIZE;
2678 } else if (version == 1) {
2679 if (pdp_getgtp1
2680 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2681 gsn->err_unknownpdp++;
2682 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
2683 len, "Unknown PDP context");
2684 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2685 len);
2686 }
jjako08d331d2003-10-13 20:33:30 +00002687
Harald Weltebed35df2011-11-02 13:06:18 +01002688 /* Is this a long or a short header ? */
2689 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2690 hlen = GTP1_HEADER_SIZE_LONG;
2691 else
2692 hlen = GTP1_HEADER_SIZE_SHORT;
2693 } else {
2694 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2695 "Unknown version");
2696 }
jjako08d331d2003-10-13 20:33:30 +00002697
Harald Weltebed35df2011-11-02 13:06:18 +01002698 /* If the GPDU was not from the peer GSN tell him to delete context */
2699 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2700 gsn->err_unknownpdp++;
2701 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2702 "Unknown PDP context");
2703 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2704 }
jjako52c24142002-12-16 13:33:51 +00002705
Harald Weltebed35df2011-11-02 13:06:18 +01002706 /* Callback function */
2707 if (gsn->cb_data_ind != 0)
2708 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2709
2710 return 0;
jjako52c24142002-12-16 13:33:51 +00002711}
2712
jjako52c24142002-12-16 13:33:51 +00002713/* Receives GTP packet and sends off for further processing
2714 * Function will check the validity of the header. If the header
2715 * is not valid the packet is either dropped or a version not
2716 * supported is returned to the peer.
2717 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002718int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002719{
Harald Weltebed35df2011-11-02 13:06:18 +01002720 unsigned char buffer[PACKET_MAX];
2721 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002722 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002723 int status;
2724 struct gtp0_header *pheader;
2725 int version = 0; /* GTP version should be determined from header! */
2726 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002727
Harald Weltebed35df2011-11-02 13:06:18 +01002728 /* TODO: Need strategy of userspace buffering and blocking */
2729 /* Currently read is non-blocking and send is blocking. */
2730 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002731
Harald Weltebed35df2011-11-02 13:06:18 +01002732 while (1) { /* Loop until no more to read */
2733 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
2734 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2735 return -1;
2736 }
2737 peerlen = sizeof(peer);
2738 if ((status =
2739 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2740 (struct sockaddr *)&peer, &peerlen)) < 0) {
2741 if (errno == EAGAIN)
2742 return 0;
2743 gsn->err_readfrom++;
2744 gtp_err(LOG_ERR, __FILE__, __LINE__,
2745 "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
2746 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2747 status, status ? strerror(errno) : "No error");
2748 return -1;
2749 }
jjako1db1c812003-07-06 20:53:57 +00002750
Harald Weltebed35df2011-11-02 13:06:18 +01002751 /* Need at least 1 byte in order to check version */
2752 if (status < (1)) {
2753 gsn->empty++;
2754 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2755 status, "Discarding packet - too small");
2756 continue;
2757 }
jjako08d331d2003-10-13 20:33:30 +00002758
Harald Weltebed35df2011-11-02 13:06:18 +01002759 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002760
Harald Weltebed35df2011-11-02 13:06:18 +01002761 /* Version should be gtp0 (or earlier) */
2762 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2763 /* GTP 0 messages. If other version message is received we reply that we */
2764 /* only support version 0, implying that this is the only version */
2765 /* supported on this port */
2766 if (((pheader->flags & 0xe0) > 0x00)) {
2767 gsn->unsup++;
2768 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2769 status, "Unsupported GTP version");
2770 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2771 continue;
2772 }
2773
2774 /* Check length of gtp0 packet */
2775 if (status < GTP0_HEADER_SIZE) {
2776 gsn->tooshort++;
2777 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2778 status, "GTP0 packet too short");
2779 continue; /* Silently discard 29.60: 11.1.2 */
2780 }
2781
2782 /* Check packet length field versus length of packet */
2783 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2784 gsn->tooshort++;
2785 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2786 status,
2787 "GTP packet length field does not match actual length");
2788 continue; /* Silently discard */
2789 }
2790
2791 if ((gsn->mode == GTP_MODE_GGSN) &&
2792 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2793 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2794 (pheader->type == GTP_DELETE_PDP_RSP))) {
2795 gsn->unexpect++;
2796 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2797 status,
2798 "Unexpected GTP Signalling Message");
2799 continue; /* Silently discard 29.60: 11.1.4 */
2800 }
2801
2802 if ((gsn->mode == GTP_MODE_SGSN) &&
2803 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2804 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2805 (pheader->type == GTP_DELETE_PDP_REQ))) {
2806 gsn->unexpect++;
2807 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2808 status,
2809 "Unexpected GTP Signalling Message");
2810 continue; /* Silently discard 29.60: 11.1.4 */
2811 }
2812
2813 switch (pheader->type) {
2814 case GTP_ECHO_REQ:
2815 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2816 break;
2817 case GTP_ECHO_RSP:
2818 gtp_echo_conf(gsn, version, &peer, buffer, status);
2819 break;
2820 case GTP_NOT_SUPPORTED:
2821 gtp_unsup_ind(gsn, &peer, buffer, status);
2822 break;
2823 case GTP_CREATE_PDP_REQ:
2824 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2825 status);
2826 break;
2827 case GTP_CREATE_PDP_RSP:
2828 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2829 status);
2830 break;
2831 case GTP_UPDATE_PDP_REQ:
2832 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2833 status);
2834 break;
2835 case GTP_UPDATE_PDP_RSP:
2836 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2837 status);
2838 break;
2839 case GTP_DELETE_PDP_REQ:
2840 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2841 status);
2842 break;
2843 case GTP_DELETE_PDP_RSP:
2844 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2845 status);
2846 break;
2847 case GTP_ERROR:
2848 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2849 break;
2850 case GTP_GPDU:
2851 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2852 break;
2853 default:
2854 gsn->unknown++;
2855 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2856 status,
2857 "Unknown GTP message type received");
2858 break;
2859 }
2860 }
jjako08d331d2003-10-13 20:33:30 +00002861}
2862
jjako08d331d2003-10-13 20:33:30 +00002863int gtp_decaps1c(struct gsn_t *gsn)
2864{
Harald Weltebed35df2011-11-02 13:06:18 +01002865 unsigned char buffer[PACKET_MAX];
2866 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002867 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002868 int status;
2869 struct gtp1_header_short *pheader;
2870 int version = 1; /* TODO GTP version should be determined from header! */
2871 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002872
Harald Weltebed35df2011-11-02 13:06:18 +01002873 /* TODO: Need strategy of userspace buffering and blocking */
2874 /* Currently read is non-blocking and send is blocking. */
2875 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002876
Harald Weltebed35df2011-11-02 13:06:18 +01002877 while (1) { /* Loop until no more to read */
2878 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
2879 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2880 return -1;
2881 }
2882 peerlen = sizeof(peer);
2883 if ((status =
2884 recvfrom(fd, buffer, sizeof(buffer), 0,
2885 (struct sockaddr *)&peer, &peerlen)) < 0) {
2886 if (errno == EAGAIN)
2887 return 0;
2888 gsn->err_readfrom++;
2889 gtp_err(LOG_ERR, __FILE__, __LINE__,
2890 "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
2891 fd, (unsigned long)buffer, sizeof(buffer),
2892 status, status ? strerror(errno) : "No error");
2893 return -1;
2894 }
jjako08d331d2003-10-13 20:33:30 +00002895
Harald Weltebed35df2011-11-02 13:06:18 +01002896 /* Need at least 1 byte in order to check version */
2897 if (status < (1)) {
2898 gsn->empty++;
2899 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2900 status, "Discarding packet - too small");
2901 continue;
2902 }
jjako08d331d2003-10-13 20:33:30 +00002903
Harald Weltebed35df2011-11-02 13:06:18 +01002904 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002905
Harald Weltebed35df2011-11-02 13:06:18 +01002906 /* Version must be no larger than GTP 1 */
2907 if (((pheader->flags & 0xe0) > 0x20)) {
2908 gsn->unsup++;
2909 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2910 status, "Unsupported GTP version");
2911 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2912 /*29.60: 11.1.1 */
2913 continue;
2914 }
jjako08d331d2003-10-13 20:33:30 +00002915
Harald Weltebed35df2011-11-02 13:06:18 +01002916 /* Version must be at least GTP 1 */
2917 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2918 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2919 /* the message */
2920 if (((pheader->flags & 0xe0) < 0x20)) {
2921 gsn->unsup++;
2922 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2923 status, "Unsupported GTP version");
2924 continue;
2925 }
jjako08d331d2003-10-13 20:33:30 +00002926
Harald Weltebed35df2011-11-02 13:06:18 +01002927 /* Check packet flag field */
2928 if (((pheader->flags & 0xf7) != 0x32)) {
2929 gsn->unsup++;
2930 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2931 status, "Unsupported packet flag");
2932 continue;
2933 }
jjako2c381332003-10-21 19:09:53 +00002934
Harald Weltebed35df2011-11-02 13:06:18 +01002935 /* Check length of packet */
2936 if (status < GTP1_HEADER_SIZE_LONG) {
2937 gsn->tooshort++;
2938 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2939 status, "GTP packet too short");
2940 continue; /* Silently discard 29.60: 11.1.2 */
2941 }
jjako2c381332003-10-21 19:09:53 +00002942
Harald Weltebed35df2011-11-02 13:06:18 +01002943 /* Check packet length field versus length of packet */
2944 if (status !=
2945 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2946 gsn->tooshort++;
2947 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2948 status,
2949 "GTP packet length field does not match actual length");
2950 continue; /* Silently discard */
2951 }
jjako1db1c812003-07-06 20:53:57 +00002952
Harald Weltebed35df2011-11-02 13:06:18 +01002953 /* Check for extension headers */
2954 /* TODO: We really should cycle through the headers and determine */
2955 /* if any have the comprehension required flag set */
2956 if (((pheader->flags & 0x04) != 0x00)) {
2957 gsn->unsup++;
2958 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2959 status, "Unsupported extension header");
2960 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2961 status);
jjako1db1c812003-07-06 20:53:57 +00002962
Harald Weltebed35df2011-11-02 13:06:18 +01002963 continue;
2964 }
2965
2966 if ((gsn->mode == GTP_MODE_GGSN) &&
2967 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2968 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2969 (pheader->type == GTP_DELETE_PDP_RSP))) {
2970 gsn->unexpect++;
2971 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2972 status,
2973 "Unexpected GTP Signalling Message");
2974 continue; /* Silently discard 29.60: 11.1.4 */
2975 }
2976
2977 if ((gsn->mode == GTP_MODE_SGSN) &&
2978 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2979 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2980 (pheader->type == GTP_DELETE_PDP_REQ))) {
2981 gsn->unexpect++;
2982 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
2983 status,
2984 "Unexpected GTP Signalling Message");
2985 continue; /* Silently discard 29.60: 11.1.4 */
2986 }
2987
2988 switch (pheader->type) {
2989 case GTP_ECHO_REQ:
2990 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2991 break;
2992 case GTP_ECHO_RSP:
2993 gtp_echo_conf(gsn, version, &peer, buffer, status);
2994 break;
2995 case GTP_NOT_SUPPORTED:
2996 gtp_unsup_ind(gsn, &peer, buffer, status);
2997 break;
2998 case GTP_SUPP_EXT_HEADER:
2999 gtp_extheader_ind(gsn, &peer, buffer, status);
3000 break;
3001 case GTP_CREATE_PDP_REQ:
3002 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3003 status);
3004 break;
3005 case GTP_CREATE_PDP_RSP:
3006 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3007 status);
3008 break;
3009 case GTP_UPDATE_PDP_REQ:
3010 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3011 status);
3012 break;
3013 case GTP_UPDATE_PDP_RSP:
3014 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3015 status);
3016 break;
3017 case GTP_DELETE_PDP_REQ:
3018 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3019 status);
3020 break;
3021 case GTP_DELETE_PDP_RSP:
3022 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3023 status);
3024 break;
3025 case GTP_ERROR:
3026 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3027 break;
3028 default:
3029 gsn->unknown++;
3030 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3031 status,
3032 "Unknown GTP message type received");
3033 break;
3034 }
3035 }
jjako52c24142002-12-16 13:33:51 +00003036}
3037
jjako08d331d2003-10-13 20:33:30 +00003038int gtp_decaps1u(struct gsn_t *gsn)
3039{
Harald Weltebed35df2011-11-02 13:06:18 +01003040 unsigned char buffer[PACKET_MAX];
3041 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003042 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003043 int status;
3044 struct gtp1_header_short *pheader;
3045 int version = 1; /* GTP version should be determined from header! */
3046 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003047
Harald Weltebed35df2011-11-02 13:06:18 +01003048 /* TODO: Need strategy of userspace buffering and blocking */
3049 /* Currently read is non-blocking and send is blocking. */
3050 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003051
Harald Weltebed35df2011-11-02 13:06:18 +01003052 while (1) { /* Loop until no more to read */
3053 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
3054 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3055 return -1;
3056 }
3057 peerlen = sizeof(peer);
3058 if ((status =
3059 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3060 (struct sockaddr *)&peer, &peerlen)) < 0) {
3061 if (errno == EAGAIN)
3062 return 0;
3063 gsn->err_readfrom++;
3064 gtp_err(LOG_ERR, __FILE__, __LINE__,
3065 "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
3066 gsn->fd1u, (unsigned long)buffer,
3067 sizeof(buffer), status,
3068 status ? strerror(errno) : "No error");
3069 return -1;
3070 }
jjako08d331d2003-10-13 20:33:30 +00003071
Harald Weltebed35df2011-11-02 13:06:18 +01003072 /* Need at least 1 byte in order to check version */
3073 if (status < (1)) {
3074 gsn->empty++;
3075 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3076 status, "Discarding packet - too small");
3077 continue;
3078 }
jjako08d331d2003-10-13 20:33:30 +00003079
Harald Weltebed35df2011-11-02 13:06:18 +01003080 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003081
Harald Weltebed35df2011-11-02 13:06:18 +01003082 /* Version must be no larger than GTP 1 */
3083 if (((pheader->flags & 0xe0) > 0x20)) {
3084 gsn->unsup++;
3085 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3086 status, "Unsupported GTP version");
3087 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3088 continue;
3089 }
jjako08d331d2003-10-13 20:33:30 +00003090
Harald Weltebed35df2011-11-02 13:06:18 +01003091 /* Version must be at least GTP 1 */
3092 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3093 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3094 /* the message */
3095 if (((pheader->flags & 0xe0) < 0x20)) {
3096 gsn->unsup++;
3097 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3098 status, "Unsupported GTP version");
3099 continue;
3100 }
jjako2c381332003-10-21 19:09:53 +00003101
Harald Weltebed35df2011-11-02 13:06:18 +01003102 /* Check packet flag field (allow both with and without sequence number) */
3103 if (((pheader->flags & 0xf5) != 0x30)) {
3104 gsn->unsup++;
3105 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3106 status, "Unsupported packet flag");
3107 continue;
3108 }
jjako2c381332003-10-21 19:09:53 +00003109
Harald Weltebed35df2011-11-02 13:06:18 +01003110 /* Check length of packet */
3111 if (status < GTP1_HEADER_SIZE_SHORT) {
3112 gsn->tooshort++;
3113 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3114 status, "GTP packet too short");
3115 continue; /* Silently discard 29.60: 11.1.2 */
3116 }
3117
3118 /* Check packet length field versus length of packet */
3119 if (status !=
3120 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3121 gsn->tooshort++;
3122 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3123 status,
3124 "GTP packet length field does not match actual length");
3125 continue; /* Silently discard */
3126 }
3127
3128 /* Check for extension headers */
3129 /* TODO: We really should cycle through the headers and determine */
3130 /* if any have the comprehension required flag set */
3131 if (((pheader->flags & 0x04) != 0x00)) {
3132 gsn->unsup++;
3133 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3134 status, "Unsupported extension header");
3135 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3136 status);
3137
3138 continue;
3139 }
3140
3141 switch (pheader->type) {
3142 case GTP_ECHO_REQ:
3143 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3144 break;
3145 case GTP_ECHO_RSP:
3146 gtp_echo_conf(gsn, version, &peer, buffer, status);
3147 break;
3148 case GTP_SUPP_EXT_HEADER:
3149 gtp_extheader_ind(gsn, &peer, buffer, status);
3150 break;
3151 case GTP_ERROR:
3152 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3153 break;
3154 /* Supported header extensions */
3155 case GTP_GPDU:
3156 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3157 break;
3158 default:
3159 gsn->unknown++;
3160 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
3161 status,
3162 "Unknown GTP message type received");
3163 break;
3164 }
3165 }
jjako08d331d2003-10-13 20:33:30 +00003166}
3167
Harald Weltebed35df2011-11-02 13:06:18 +01003168int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003169{
Harald Weltebed35df2011-11-02 13:06:18 +01003170 union gtp_packet packet;
3171 struct sockaddr_in addr;
3172 int fd;
3173 int length;
jjako52c24142002-12-16 13:33:51 +00003174
Harald Weltebed35df2011-11-02 13:06:18 +01003175 memset(&addr, 0, sizeof(addr));
3176 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003177#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003178 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003179#endif
3180
Harald Weltebed35df2011-11-02 13:06:18 +01003181 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003182
Harald Weltebed35df2011-11-02 13:06:18 +01003183 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003184
Harald Weltebed35df2011-11-02 13:06:18 +01003185 length = GTP0_HEADER_SIZE + len;
3186 addr.sin_port = htons(GTP0_PORT);
3187 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003188
Harald Weltebed35df2011-11-02 13:06:18 +01003189 get_default_gtp(0, GTP_GPDU, &packet);
3190 packet.gtp0.h.length = hton16(len);
3191 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3192 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003193 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003194
Harald Weltebed35df2011-11-02 13:06:18 +01003195 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3196 gsn->err_memcpy++;
3197 gtp_err(LOG_ERR, __FILE__, __LINE__,
3198 "Memcpy failed: %d > %d", len,
3199 sizeof(union gtp_packet) -
3200 sizeof(struct gtp0_header));
3201 return EOF;
3202 }
3203 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3204 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003205
Harald Weltebed35df2011-11-02 13:06:18 +01003206 length = GTP1_HEADER_SIZE_LONG + len;
3207 addr.sin_port = htons(GTP1U_PORT);
3208 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003209
Harald Weltebed35df2011-11-02 13:06:18 +01003210 get_default_gtp(1, GTP_GPDU, &packet);
3211 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3212 GTP1_HEADER_SIZE_LONG);
3213 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3214 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3215
3216 if (len >
3217 sizeof(union gtp_packet) -
3218 sizeof(struct gtp1_header_long)) {
3219 gsn->err_memcpy++;
3220 gtp_err(LOG_ERR, __FILE__, __LINE__,
3221 "Memcpy failed: %d > %d", len,
3222 sizeof(union gtp_packet) -
3223 sizeof(struct gtp0_header));
3224 return EOF;
3225 }
3226 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3227 } else {
3228 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
3229 return EOF;
3230 }
3231
3232 if (fcntl(fd, F_SETFL, 0)) {
3233 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3234 return -1;
3235 }
3236
3237 if (sendto(fd, &packet, length, 0,
3238 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3239 gsn->err_sendto++;
3240 gtp_err(LOG_ERR, __FILE__, __LINE__,
3241 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
3242 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3243 strerror(errno));
3244 return EOF;
3245 }
3246 return 0;
jjako52c24142002-12-16 13:33:51 +00003247}
3248
jjako52c24142002-12-16 13:33:51 +00003249/* ***********************************************************
3250 * Conversion functions
3251 *************************************************************/
3252
Harald Weltebed35df2011-11-02 13:06:18 +01003253int char2ul_t(char *src, struct ul_t dst)
3254{
3255 dst.l = strlen(src) + 1;
3256 dst.v = malloc(dst.l);
3257 dst.v[0] = dst.l - 1;
3258 memcpy(&dst.v[1], src, dst.v[0]);
3259 return 0;
jjako52c24142002-12-16 13:33:51 +00003260}
3261
3262/* ***********************************************************
3263 * IP address conversion functions
3264 * There exist several types of address representations:
3265 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3266 * Used for signalling address to mobile station. Supports IPv4
3267 * IPv6 x.25 etc. etc.
3268 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3269 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3270 * - in_addr: IPv4 address struct.
3271 * - sockaddr_in: Socket API representation of IP address and
3272 * port number.
3273 *************************************************************/
3274
Harald Weltebed35df2011-11-02 13:06:18 +01003275int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3276{
3277 eua->v[0] = 0xf1; /* IETF */
3278 eua->v[1] = 0x21; /* IPv4 */
3279 if (src) {
3280 eua->l = 6;
3281 memcpy(&eua->v[2], src, 4);
3282 } else {
3283 eua->l = 2;
3284 }
3285 return 0;
jjako52c24142002-12-16 13:33:51 +00003286}
3287
Harald Weltebed35df2011-11-02 13:06:18 +01003288int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3289{
3290 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3291 return -1; /* Not IPv4 address */
3292 memcpy(dst, &eua->v[2], 4);
3293 return 0;
jjako52c24142002-12-16 13:33:51 +00003294}
3295
Harald Weltebed35df2011-11-02 13:06:18 +01003296int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3297{
3298 memset(dst, 0, sizeof(struct in_addr));
3299 if (gsna->l != 4)
3300 return EOF; /* Return if not IPv4 */
3301 memcpy(dst, gsna->v, gsna->l);
3302 return 0;
jjako52c24142002-12-16 13:33:51 +00003303}
3304
Harald Weltebed35df2011-11-02 13:06:18 +01003305int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3306{
3307 memset(gsna, 0, sizeof(struct ul16_t));
3308 gsna->l = 4;
3309 memcpy(gsna->v, src, gsna->l);
3310 return 0;
jjako52c24142002-12-16 13:33:51 +00003311}