blob: 08a9d61bf7a189ddd5d216208fdcb803af0648e5 [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
jjako0fe0df02004-09-17 11:30:40 +00003 * Copyright (C) 2002, 2003, 2004 Mondru AB.
jjako52c24142002-12-16 13:33:51 +00004 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
jjako52c24142002-12-16 13:33:51 +000010 */
11
12/*
13 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
14 * tunnels in the same program.
15 *
16 * TODO:
17 * - Do we need to handle fragmentation?
18 */
19
jjako52c24142002-12-16 13:33:51 +000020#ifdef __linux__
21#define _GNU_SOURCE 1
22#endif
23
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010024#include <osmocom/core/logging.h>
25#include <osmocom/core/utils.h>
26
Holger Hans Peter Freyther5816bcf2014-04-04 11:43:09 +020027#if defined(__FreeBSD__)
28#include <sys/endian.h>
29#endif
30
jjako0fe0df02004-09-17 11:30:40 +000031#include "../config.h"
32#ifdef HAVE_STDINT_H
33#include <stdint.h>
34#endif
jjako52c24142002-12-16 13:33:51 +000035
jjako52c24142002-12-16 13:33:51 +000036#include <stdio.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <sys/time.h>
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <netinet/in.h>
43#include <arpa/inet.h>
44#include <sys/stat.h>
45#include <time.h>
46#include <unistd.h>
47#include <string.h>
48#include <errno.h>
49#include <fcntl.h>
50
51#include <arpa/inet.h>
52
jjakobae2cd42004-01-09 12:04:39 +000053/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000054
55#include "pdp.h"
56#include "gtp.h"
57#include "gtpie.h"
58#include "queue.h"
59
Harald Welte95848ba2011-11-02 18:17:50 +010060/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
61#define N3_REQUESTS 5
62
63#define T3_REQUEST 3
64
jjako1db1c812003-07-06 20:53:57 +000065/* Error reporting functions */
66
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010067#define GTP_LOGPKG(pri, peer, pack, len, fmt, args...) \
68 logp2(DLGTP, pri, __FILE__, __LINE__, 0, \
69 "Packet from %s:%u, length: %d content: %s: " fmt, \
70 inet_ntoa((peer)->sin_addr), htons((peer)->sin_port), \
71 len, osmo_hexdump((const uint8_t *) pack, len), \
72 ##args);
jjako1db1c812003-07-06 20:53:57 +000073
Neels Hofmeyr9b097382015-10-12 14:00:19 +020074#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
75 LOGP(ss, level, "addr(%s:%d) " fmt, \
76 inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
77 ##args);
78
jjako52c24142002-12-16 13:33:51 +000079/* API Functions */
80
Harald Weltebed35df2011-11-02 13:06:18 +010081const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +000082{
Harald Weltebed35df2011-11-02 13:06:18 +010083 return VERSION;
jjako52c24142002-12-16 13:33:51 +000084}
85
86/* gtp_new */
87/* gtp_free */
88
Harald Weltebed35df2011-11-02 13:06:18 +010089int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
90 uint64_t imsi, uint8_t nsapi)
91{
92 return pdp_newpdp(pdp, imsi, nsapi, NULL);
jjako52c24142002-12-16 13:33:51 +000093}
94
Harald Weltebed35df2011-11-02 13:06:18 +010095int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
96{
97 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +000098}
99
jjako52c24142002-12-16 13:33:51 +0000100/* gtp_gpdu */
101
Harald Weltebed35df2011-11-02 13:06:18 +0100102extern int gtp_fd(struct gsn_t *gsn)
103{
104 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000105}
106
107/* gtp_decaps */
108/* gtp_retrans */
109/* gtp_retranstimeout */
110
jjako08d331d2003-10-13 20:33:30 +0000111int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100112 int (*cb) (struct sockaddr_in * peer))
113{
114 gsn->cb_unsup_ind = cb;
115 return 0;
jjako08d331d2003-10-13 20:33:30 +0000116}
117
jjako2c381332003-10-21 19:09:53 +0000118int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100119 int (*cb) (struct sockaddr_in * peer))
120{
121 gsn->cb_extheader_ind = cb;
122 return 0;
jjako2c381332003-10-21 19:09:53 +0000123}
124
jjako08d331d2003-10-13 20:33:30 +0000125/* API: Initialise delete context callback */
126/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100127int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000128{
Harald Weltebed35df2011-11-02 13:06:18 +0100129 gsn->cb_delete_context = cb;
130 return 0;
jjako52c24142002-12-16 13:33:51 +0000131}
132
jjako52c24142002-12-16 13:33:51 +0000133int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100134 int (*cb) (int type, int cause,
135 struct pdp_t * pdp, void *cbp))
136{
137 gsn->cb_conf = cb;
138 return 0;
jjako52c24142002-12-16 13:33:51 +0000139}
140
Harald Welte629e9862010-12-24 20:58:09 +0100141int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100142 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
143{
144 gsn->cb_recovery = cb;
145 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100146}
147
jjako08d331d2003-10-13 20:33:30 +0000148extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100149 int (*cb_data_ind) (struct pdp_t * pdp,
150 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000151{
Harald Weltebed35df2011-11-02 13:06:18 +0100152 gsn->cb_data_ind = cb_data_ind;
153 return 0;
jjako52c24142002-12-16 13:33:51 +0000154}
155
jjako08d331d2003-10-13 20:33:30 +0000156/**
157 * get_default_gtp()
158 * Generate a GPRS Tunneling Protocol signalling packet header, depending
159 * on GTP version and message type. pdp is used for teid/flow label.
160 * *packet must be allocated by the calling function, and be large enough
161 * to hold the packet header.
162 * returns the length of the header. 0 on error.
163 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100164static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
165{
166 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
167 struct gtp1_header_long *gtp1_default =
168 (struct gtp1_header_long *)packet;
169 switch (version) {
170 case 0:
171 /* Initialise "standard" GTP0 header */
172 memset(gtp0_default, 0, sizeof(struct gtp0_header));
173 gtp0_default->flags = 0x1e;
174 gtp0_default->type = hton8(type);
175 gtp0_default->spare1 = 0xff;
176 gtp0_default->spare2 = 0xff;
177 gtp0_default->spare3 = 0xff;
178 gtp0_default->number = 0xff;
179 return GTP0_HEADER_SIZE;
180 case 1:
181 /* Initialise "standard" GTP1 header */
182 /* 29.060: 8.2: S=1 and PN=0 */
183 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
184 /* and Supported Extension Headers Notification, the S field shall be */
185 /* set to 1 */
186 /* Currently extension headers are not supported */
187 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
188 gtp1_default->flags = 0x32; /* No extension, enable sequence, no N-PDU */
189 gtp1_default->type = hton8(type);
190 return GTP1_HEADER_SIZE_LONG;
191 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100192 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100193 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100194 return 0;
195 }
jjako52c24142002-12-16 13:33:51 +0000196}
197
jjako08d331d2003-10-13 20:33:30 +0000198/**
199 * get_seq()
200 * Get sequence number of a packet.
201 * Returns 0 on error
202 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100203static uint16_t get_seq(void *pack)
204{
205 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000206
Harald Weltebed35df2011-11-02 13:06:18 +0100207 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
208 return ntoh16(packet->gtp0.h.seq);
209 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
210 return ntoh16(packet->gtp1l.h.seq);
211 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100212 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100213 return 0;
214 }
jjako08d331d2003-10-13 20:33:30 +0000215}
216
217/**
218 * get_tid()
219 * Get tunnel identifier of a packet.
220 * Returns 0 on error
221 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100222static uint64_t get_tid(void *pack)
223{
224 union gtp_packet *packet = (union gtp_packet *)pack;
225
226 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100227 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100228 }
229 return 0;
jjako08d331d2003-10-13 20:33:30 +0000230}
231
232/**
233 * get_hlen()
234 * Get the header length of a packet.
235 * Returns 0 on error
236 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100237static uint16_t get_hlen(void *pack)
238{
239 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000240
Harald Weltebed35df2011-11-02 13:06:18 +0100241 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
242 return GTP0_HEADER_SIZE;
243 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
244 return GTP1_HEADER_SIZE_LONG;
245 } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
246 return GTP1_HEADER_SIZE_SHORT;
247 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100248 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100249 return 0;
250 }
jjako08d331d2003-10-13 20:33:30 +0000251}
252
253/**
254 * get_tei()
255 * Get the tunnel endpoint identifier (flow label) of a packet.
256 * Returns 0xffffffff on error.
257 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100258static uint32_t get_tei(void *pack)
259{
260 union gtp_packet *packet = (union gtp_packet *)pack;
jjako08d331d2003-10-13 20:33:30 +0000261
Harald Weltebed35df2011-11-02 13:06:18 +0100262 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
263 return ntoh16(packet->gtp0.h.flow);
264 } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
265 return ntoh32(packet->gtp1l.h.tei);
266 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100267 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100268 return 0xffffffff;
269 }
jjako08d331d2003-10-13 20:33:30 +0000270}
jjakoa7cd2492003-04-11 09:40:12 +0000271
jjako52c24142002-12-16 13:33:51 +0000272/* ***********************************************************
273 * Reliable delivery of signalling messages
274 *
275 * Sequence numbers are used for both signalling messages and
276 * data messages.
277 *
278 * For data messages each tunnel maintains a sequence counter,
279 * which is incremented by one each time a new data message
280 * is sent. The sequence number starts at (0) zero at tunnel
281 * establishment, and wraps around at 65535 (29.060 9.3.1.1
282 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
283 * or can be used to check the validity of the message in the
284 * receiver, or for reordering af packets.
285 *
286 * For signalling messages the sequence number is used by
287 * signalling messages for which a response is defined. A response
288 * message should copy the sequence from the corresponding request
289 * message. The sequence number "unambiguously" identifies a request
290 * message within a given path, with a path being defined as a set of
291 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
292 * messages shall be responded to, and all response messages associated
293 * with a certain request shall always include the same information"
294 *
295 * We take this to mean that the GSN transmitting a request is free to
296 * choose the sequence number, as long as it is unique within a given path.
297 * It means that we are allowed to count backwards, or roll over at 17
298 * if we prefer that. It also means that we can use the same counter for
299 * all paths. This has the advantage that the transmitted request sequence
300 * numbers are unique within each GSN, and also we dont have to mess around
301 * with path setup and teardown.
302 *
303 * If a response message is lost, the request will be retransmitted, and
304 * the receiving GSN will receive a "duplicated" request. The standard
305 * requires the receiving GSN to send a response, with the same information
306 * as in the original response. For most messages this happens automatically:
307 *
308 * Echo: Automatically dublicates the original response
309 * Create pdp context: The SGSN may send create context request even if
310 * a context allready exist (imsi+nsapi?). This means that the reply will
311 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000312 * side effects in the application which is asked twice to validate
313 * the login.
jjako52c24142002-12-16 13:33:51 +0000314 * Update pdp context: Automatically dublicates the original response???
315 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
316 * a nonexist reply message.
317 *
318 * The correct solution will be to make a queue containing response messages.
319 * This queue should be checked whenever a request is received. If the
320 * response is allready in the queue that response should be transmitted.
321 * It should be possible to find messages in this queue on the basis of
322 * the sequence number and peer GSN IP address (The sequense number is unique
323 * within each path). This need to be implemented by a hash table. Furthermore
324 * it should be possibly to delete messages based on a timeout. This can be
325 * achieved by means of a linked list. The timeout value need to be larger
326 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
327 * set in the peer GSN, so there is no way to know these parameters. On the
328 * other hand the timeout value need to be so small that we do not receive
329 * wraparound sequence numbere before the message is deleted. 60 seconds is
330 * probably not a bad choise.
331 *
332 * This queue however is first really needed from gtp1.
333 *
334 * gtp_req:
335 * Send off a signalling message with appropiate sequence
336 * number. Store packet in queue.
337 * gtp_conf:
338 * Remove an incoming confirmation from the queue
339 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000340 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000341 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000342 * gtp_notification:
343 * Send off a notification message. This is neither a request nor
344 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000345 * gtp_retrans:
346 * Retransmit any outstanding packets which have exceeded
347 * a predefined timeout.
348 *************************************************************/
349
jjako08d331d2003-10-13 20:33:30 +0000350int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100351 union gtp_packet *packet, int len,
352 struct in_addr *inetaddr, void *cbp)
353{
354 struct sockaddr_in addr;
355 struct qmsg_t *qmsg;
356 int fd;
jjako08d331d2003-10-13 20:33:30 +0000357
Harald Weltebed35df2011-11-02 13:06:18 +0100358 memset(&addr, 0, sizeof(addr));
359 addr.sin_family = AF_INET;
360 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000361#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100362 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000363#endif
jjako52c24142002-12-16 13:33:51 +0000364
Harald Weltebed35df2011-11-02 13:06:18 +0100365 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
366 addr.sin_port = htons(GTP0_PORT);
367 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
368 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100369 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100370 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100371 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100372 }
Harald Weltebed35df2011-11-02 13:06:18 +0100373 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
374 || (packet->gtp0.h.type == GTP_ERROR)))
375 packet->gtp0.h.flow = hton16(pdp->flru);
376 else if (pdp)
377 packet->gtp0.h.flow = hton16(pdp->flrc);
378 fd = gsn->fd0;
379 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
380 addr.sin_port = htons(GTP1C_PORT);
381 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
382 packet->gtp1l.h.seq = hton16(gsn->seq_next);
383 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
384 (packet->gtp1l.h.type == GTP_ERROR)))
385 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
386 else if (pdp)
387 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
388 fd = gsn->fd1c;
389 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100390 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100391 return -1;
392 }
jjako52c24142002-12-16 13:33:51 +0000393
Harald Weltebed35df2011-11-02 13:06:18 +0100394 if (sendto(fd, packet, len, 0,
395 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
396 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100397 LOGP(DLGTP, LOGL_ERROR,
398 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100399 (unsigned long)&packet, len, strerror(errno));
400 return -1;
401 }
402
403 /* Use new queue structure */
404 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
405 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100406 LOGP(DLGTP, LOGL_ERROR,
407 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100408 } else {
409 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
410 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100411 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100412 qmsg->retrans = 0; /* No retransmissions so far */
413 qmsg->cbp = cbp;
414 qmsg->type = ntoh8(packet->gtp0.h.type);
415 qmsg->fd = fd;
416 }
417 gsn->seq_next++; /* Count up this time */
418 return 0;
jjako52c24142002-12-16 13:33:51 +0000419}
420
421/* gtp_conf
422 * Remove signalling packet from retransmission queue.
423 * return 0 on success, EOF if packet was not found */
424
425int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100426 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
427{
jjako52c24142002-12-16 13:33:51 +0000428
Harald Weltebed35df2011-11-02 13:06:18 +0100429 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000430
Harald Weltebed35df2011-11-02 13:06:18 +0100431 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
432 seq = ntoh16(packet->gtp0.h.seq);
433 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
434 seq = ntoh16(packet->gtp1l.h.seq);
435 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100436 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
437 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100438 return EOF;
439 }
jjako08d331d2003-10-13 20:33:30 +0000440
Harald Weltebed35df2011-11-02 13:06:18 +0100441 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
442 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100443 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
444 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100445 return EOF;
446 }
jjako52c24142002-12-16 13:33:51 +0000447
Harald Weltebed35df2011-11-02 13:06:18 +0100448 return 0;
jjako52c24142002-12-16 13:33:51 +0000449}
450
Harald Weltebed35df2011-11-02 13:06:18 +0100451int gtp_retrans(struct gsn_t *gsn)
452{
453 /* Retransmit any outstanding packets */
454 /* Remove from queue if maxretrans exceeded */
455 time_t now;
456 struct qmsg_t *qmsg;
457 now = time(NULL);
458 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000459
Harald Welte95848ba2011-11-02 18:17:50 +0100460 /* get first element in queue, as long as the timeout of that
461 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100462 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
463 (qmsg->timeout <= now)) {
464 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100465 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100466 if (gsn->cb_conf)
467 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
468 queue_freemsg(gsn->queue_req, qmsg);
469 } else {
470 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
471 (struct sockaddr *)&qmsg->peer,
472 sizeof(struct sockaddr_in)) < 0) {
473 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100474 LOGP(DLGTP, LOGL_ERROR,
475 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100476 gsn->fd0, (unsigned long)&qmsg->p,
477 qmsg->l, strerror(errno));
478 }
479 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100480 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100481 qmsg->retrans++;
482 }
483 }
jjako52c24142002-12-16 13:33:51 +0000484
Harald Weltebed35df2011-11-02 13:06:18 +0100485 /* Also clean up reply timeouts */
486 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
487 (qmsg->timeout < now)) {
488 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
489 queue_freemsg(gsn->queue_resp, qmsg);
490 }
jjako52c24142002-12-16 13:33:51 +0000491
Harald Weltebed35df2011-11-02 13:06:18 +0100492 return 0;
jjako52c24142002-12-16 13:33:51 +0000493}
494
Harald Weltebed35df2011-11-02 13:06:18 +0100495int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
496{
497 time_t now, later;
498 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000499
Harald Weltebed35df2011-11-02 13:06:18 +0100500 if (queue_getfirst(gsn->queue_req, &qmsg)) {
501 timeout->tv_sec = 10;
502 timeout->tv_usec = 0;
503 } else {
504 now = time(NULL);
505 later = qmsg->timeout;
506 timeout->tv_sec = later - now;
507 timeout->tv_usec = 0;
508 if (timeout->tv_sec < 0)
509 timeout->tv_sec = 0; /* No negative allowed */
510 if (timeout->tv_sec > 10)
511 timeout->tv_sec = 10; /* Max sleep for 10 sec */
512 }
513 return 0;
jjako52c24142002-12-16 13:33:51 +0000514}
515
Harald Weltebed35df2011-11-02 13:06:18 +0100516int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000517 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100518 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
519{
520 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000521
Harald Weltebed35df2011-11-02 13:06:18 +0100522 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
523 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
524 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100525 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100526 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
527 (packet->gtp0.h.type == GTP_ERROR)))
528 packet->gtp0.h.flow = hton16(pdp->flru);
529 else if (pdp)
530 packet->gtp0.h.flow = hton16(pdp->flrc);
531 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
532 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
533 packet->gtp1l.h.seq = hton16(seq);
534 if (pdp && (fd == gsn->fd1u))
535 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
536 else if (pdp)
537 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
538 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100539 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100540 return -1;
541 }
jjako08d331d2003-10-13 20:33:30 +0000542
Harald Weltebed35df2011-11-02 13:06:18 +0100543 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100544 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100545 return -1;
546 }
jjako52c24142002-12-16 13:33:51 +0000547
Harald Weltebed35df2011-11-02 13:06:18 +0100548 if (sendto(fd, packet, len, 0,
549 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
550 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100551 LOGP(DLGTP, LOGL_ERROR,
552 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100553 (unsigned long)&packet, len, strerror(errno));
554 return -1;
555 }
556
557 /* Use new queue structure */
558 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
559 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100560 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100561 } else {
562 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
563 qmsg->l = len;
564 qmsg->timeout = time(NULL) + 60; /* When to timeout */
565 qmsg->retrans = 0; /* No retransmissions so far */
566 qmsg->cbp = NULL;
567 qmsg->type = 0;
568 qmsg->fd = fd;
569 }
570 return 0;
jjako52c24142002-12-16 13:33:51 +0000571}
572
jjako2c381332003-10-21 19:09:53 +0000573int gtp_notification(struct gsn_t *gsn, int version,
574 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100575 struct sockaddr_in *peer, int fd, uint16_t seq)
576{
jjako2c381332003-10-21 19:09:53 +0000577
Harald Weltebed35df2011-11-02 13:06:18 +0100578 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000579
Harald Weltebed35df2011-11-02 13:06:18 +0100580 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000581
Harald Weltebed35df2011-11-02 13:06:18 +0100582 /* In GTP0 notifications are treated as replies. In GTP1 they
583 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000584
Harald Weltebed35df2011-11-02 13:06:18 +0100585 if (fd == gsn->fd1c)
586 addr.sin_port = htons(GTP1C_PORT);
587 else if (fd == gsn->fd1u)
588 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000589
Harald Weltebed35df2011-11-02 13:06:18 +0100590 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
591 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
592 packet->gtp0.h.seq = hton16(seq);
593 } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
594 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
595 packet->gtp1l.h.seq = hton16(seq);
596 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100597 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flag: %u\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100598 return -1;
599 }
600
601 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100602 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100603 return -1;
604 }
605
606 if (sendto(fd, packet, len, 0,
607 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
608 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100609 LOGP(DLGTP, LOGL_ERROR,
610 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100611 (unsigned long)&packet, len, strerror(errno));
612 return -1;
613 }
614 return 0;
jjako2c381332003-10-21 19:09:53 +0000615}
616
Harald Weltebed35df2011-11-02 13:06:18 +0100617int gtp_dublicate(struct gsn_t *gsn, int version,
618 struct sockaddr_in *peer, uint16_t seq)
619{
620 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000621
Harald Weltebed35df2011-11-02 13:06:18 +0100622 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
623 return EOF; /* Notfound */
624 }
jjakoa7cd2492003-04-11 09:40:12 +0000625
Harald Weltebed35df2011-11-02 13:06:18 +0100626 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100627 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100628 return -1;
629 }
630
631 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
632 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
633 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100634 LOGP(DLGTP, LOGL_ERROR,
635 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100636 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
637 strerror(errno));
638 }
639 return 0;
jjako52c24142002-12-16 13:33:51 +0000640}
641
jjako52c24142002-12-16 13:33:51 +0000642/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100643static void log_restart(struct gsn_t *gsn)
644{
jjako52c24142002-12-16 13:33:51 +0000645 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200646 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000647 int counter = 0;
648 char filename[NAMESIZE];
649
Harald Weltebed35df2011-11-02 13:06:18 +0100650 filename[NAMESIZE - 1] = 0; /* No null term. guarantee by strncpy */
651 strncpy(filename, gsn->statedir, NAMESIZE - 1);
652 strncat(filename, RESTART_FILE, NAMESIZE - 1 - sizeof(RESTART_FILE));
jjako52c24142002-12-16 13:33:51 +0000653
654 i = umask(022);
655
656 /* We try to open file. On failure we will later try to create file */
657 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100658 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100659 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100660 filename);
661 } else {
662 umask(i);
663 rc = fscanf(f, "%d", &counter);
664 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100665 LOGP(DLGTP, LOGL_ERROR,
666 "fscanf failed to read counter value\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100667 return;
668 }
669 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100670 LOGP(DLGTP, LOGL_ERROR,
671 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100672 }
jjako52c24142002-12-16 13:33:51 +0000673 }
Harald Weltebed35df2011-11-02 13:06:18 +0100674
675 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000676 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100677
jjako52c24142002-12-16 13:33:51 +0000678 if (!(f = fopen(filename, "w"))) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100679 LOGP(DLGTP, LOGL_ERROR,
680 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100681 "w", strerror(errno));
682 return;
jjako52c24142002-12-16 13:33:51 +0000683 }
684
685 umask(i);
686 fprintf(f, "%d\n", gsn->restart_counter);
687 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100688 LOGP(DLGTP, LOGL_ERROR,
689 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100690 return;
jjako52c24142002-12-16 13:33:51 +0000691 }
692}
693
jjako1db1c812003-07-06 20:53:57 +0000694int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100695 int mode)
jjako52c24142002-12-16 13:33:51 +0000696{
Harald Weltebed35df2011-11-02 13:06:18 +0100697 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000698
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100699 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started\n");
jjako52c24142002-12-16 13:33:51 +0000700
Harald Weltebed35df2011-11-02 13:06:18 +0100701 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000702
Harald Weltebed35df2011-11-02 13:06:18 +0100703 (*gsn)->statedir = statedir;
704 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000705
Harald Weltebed35df2011-11-02 13:06:18 +0100706 /* Initialise sequence number */
707 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000708
Harald Weltebed35df2011-11-02 13:06:18 +0100709 /* Initialise request retransmit queue */
710 queue_new(&(*gsn)->queue_req);
711 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000712
Harald Weltebed35df2011-11-02 13:06:18 +0100713 /* Initialise pdp table */
714 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000715
Harald Weltebed35df2011-11-02 13:06:18 +0100716 /* Initialise call back functions */
717 (*gsn)->cb_create_context_ind = 0;
718 (*gsn)->cb_delete_context = 0;
719 (*gsn)->cb_unsup_ind = 0;
720 (*gsn)->cb_conf = 0;
721 (*gsn)->cb_data_ind = 0;
722
723 /* Store function parameters */
724 (*gsn)->gsnc = *listen;
725 (*gsn)->gsnu = *listen;
726 (*gsn)->mode = mode;
727
728 /* Create GTP version 0 socket */
729 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
730 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100731 LOGP(DLGTP, LOGL_ERROR,
732 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100733 AF_INET, SOCK_DGRAM, 0, strerror(errno));
734 return -1;
735 }
736
737 memset(&addr, 0, sizeof(addr));
738 addr.sin_family = AF_INET;
739 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
740 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000741#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100742 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000743#endif
jjako08d331d2003-10-13 20:33:30 +0000744
Harald Weltebed35df2011-11-02 13:06:18 +0100745 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
746 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200747 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
748 "bind(fd0=%d) failed: Error = %s\n",
749 (*gsn)->fd0, strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100750 return -1;
751 }
jjako08d331d2003-10-13 20:33:30 +0000752
Harald Weltebed35df2011-11-02 13:06:18 +0100753 /* Create GTP version 1 control plane socket */
754 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
755 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100756 LOGP(DLGTP, LOGL_ERROR,
757 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100758 AF_INET, SOCK_DGRAM, 0, strerror(errno));
759 return -1;
760 }
761
762 memset(&addr, 0, sizeof(addr));
763 addr.sin_family = AF_INET;
764 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
765 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000766#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100767 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000768#endif
jjako08d331d2003-10-13 20:33:30 +0000769
Harald Weltebed35df2011-11-02 13:06:18 +0100770 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
771 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200772 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
773 "bind(fd1c=%d) failed: Error = %s\n",
774 (*gsn)->fd1c, strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100775 return -1;
776 }
jjako08d331d2003-10-13 20:33:30 +0000777
Harald Weltebed35df2011-11-02 13:06:18 +0100778 /* Create GTP version 1 user plane socket */
779 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
780 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100781 LOGP(DLGTP, LOGL_ERROR,
782 "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100783 AF_INET, SOCK_DGRAM, 0, strerror(errno));
784 return -1;
785 }
786
787 memset(&addr, 0, sizeof(addr));
788 addr.sin_family = AF_INET;
789 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
790 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000791#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100792 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000793#endif
jjako52c24142002-12-16 13:33:51 +0000794
Harald Weltebed35df2011-11-02 13:06:18 +0100795 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
796 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200797 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
798 "bind(fd1c=%d) failed: Error = %s\n",
799 (*gsn)->fd1c, strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100800 return -1;
801 }
802
803 return 0;
jjako52c24142002-12-16 13:33:51 +0000804}
805
Harald Weltebed35df2011-11-02 13:06:18 +0100806int gtp_free(struct gsn_t *gsn)
807{
jjako52c24142002-12-16 13:33:51 +0000808
Harald Weltebed35df2011-11-02 13:06:18 +0100809 /* Clean up retransmit queues */
810 queue_free(gsn->queue_req);
811 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000812
Harald Weltebed35df2011-11-02 13:06:18 +0100813 close(gsn->fd0);
814 close(gsn->fd1c);
815 close(gsn->fd1u);
816
817 free(gsn);
818 return 0;
jjako52c24142002-12-16 13:33:51 +0000819}
820
821/* ***********************************************************
822 * Path management messages
823 * Messages: echo and version not supported.
824 * A path is connection between two UDP/IP endpoints
825 *
826 * A path is either using GTP0 or GTP1. A path can be
827 * established by any kind of GTP message??
828
829 * Which source port to use?
830 * GTP-C request destination port is 2123/3386
831 * GTP-U request destination port is 2152/3386
832 * T-PDU destination port is 2152/3386.
833 * For the above messages the source port is locally allocated.
834 * For response messages src=rx-dst and dst=rx-src.
835 * For simplicity we should probably use 2123+2152/3386 as
836 * src port even for the cases where src can be locally
837 * allocated. This also means that we have to listen only to
838 * the same ports.
839 * For response messages we need to be able to respond to
840 * the relevant src port even if it is locally allocated by
841 * the peer.
842 *
843 * The need for path management!
844 * We might need to keep a list of active paths. This might
845 * be in the form of remote IP address + UDP port numbers.
846 * (We will consider a path astablished if we have a context
847 * with the node in question)
848 *************************************************************/
849
850/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000851int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
852 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000853{
Harald Weltebed35df2011-11-02 13:06:18 +0100854 union gtp_packet packet;
855 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
856 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000857}
858
jjako08d331d2003-10-13 20:33:30 +0000859/* Send off an echo reply */
860int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100861 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000862{
Harald Weltebed35df2011-11-02 13:06:18 +0100863 union gtp_packet packet;
864 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
865 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
866 gsn->restart_counter);
867 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
868 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000869}
870
jjako52c24142002-12-16 13:33:51 +0000871/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100872int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
873 int fd, void *pack, unsigned len)
874{
jjako52c24142002-12-16 13:33:51 +0000875
Harald Weltebed35df2011-11-02 13:06:18 +0100876 /* Check if it was a dublicate request */
877 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
878 return 0;
jjako52c24142002-12-16 13:33:51 +0000879
Harald Weltebed35df2011-11-02 13:06:18 +0100880 /* Send off reply to request */
881 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000882}
883
884/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000885int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100886 void *pack, unsigned len)
887{
888 union gtpie_member *ie[GTPIE_SIZE];
889 unsigned char recovery;
890 void *cbp = NULL;
891 uint8_t type = 0;
892 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000893
Harald Weltebed35df2011-11-02 13:06:18 +0100894 /* Remove packet from queue */
895 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
896 return EOF;
jjako52c24142002-12-16 13:33:51 +0000897
Harald Weltebed35df2011-11-02 13:06:18 +0100898 /* Extract information elements into a pointer array */
899 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
900 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100901 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
902 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100903 if (gsn->cb_conf)
904 gsn->cb_conf(type, EOF, NULL, cbp);
905 return EOF;
906 }
jjako52c24142002-12-16 13:33:51 +0000907
Harald Weltebed35df2011-11-02 13:06:18 +0100908 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
909 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100910 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
911 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100912 if (gsn->cb_conf)
913 gsn->cb_conf(type, EOF, NULL, cbp);
914 return EOF;
915 }
jjako52c24142002-12-16 13:33:51 +0000916
Harald Weltebed35df2011-11-02 13:06:18 +0100917 /* Echo reply packages does not have a cause information element */
918 /* Instead we return the recovery number in the callback function */
919 if (gsn->cb_conf)
920 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100921
Harald Weltebed35df2011-11-02 13:06:18 +0100922 if (gsn->cb_recovery)
923 gsn->cb_recovery(peer, recovery);
924
925 return 0;
jjako52c24142002-12-16 13:33:51 +0000926}
927
928/* Send off a Version Not Supported message */
929/* This message is somewhat special in that it actually is a
930 * response to some other message with unsupported GTP version
931 * For this reason it has parameters like a response, and does
932 * its own message transmission. No signalling queue is used
933 * The reply is sent to the peer IP and peer UDP. This means that
934 * the peer will be receiving a GTP0 message on a GTP1 port!
935 * In practice however this will never happen as a GTP0 GSN will
936 * only listen to the GTP0 port, and therefore will never receive
937 * anything else than GTP0 */
938
jjako08d331d2003-10-13 20:33:30 +0000939int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
940 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000941{
Harald Weltebed35df2011-11-02 13:06:18 +0100942 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000943
Harald Weltebed35df2011-11-02 13:06:18 +0100944 /* GTP 1 is the highest supported protocol */
945 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
946 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000947}
948
949/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +0100950int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
951 void *pack, unsigned len)
952{
jjako52c24142002-12-16 13:33:51 +0000953
Harald Weltebed35df2011-11-02 13:06:18 +0100954 if (gsn->cb_unsup_ind)
955 gsn->cb_unsup_ind(peer);
956
957 return 0;
jjako52c24142002-12-16 13:33:51 +0000958}
959
jjako2c381332003-10-21 19:09:53 +0000960/* Send off an Supported Extension Headers Notification */
961int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
962 int fd, void *pack, unsigned len)
963{
Harald Weltebed35df2011-11-02 13:06:18 +0100964 union gtp_packet packet;
965 unsigned int length =
966 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +0000967
Harald Weltebed35df2011-11-02 13:06:18 +0100968 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +0000969
Harald Weltebed35df2011-11-02 13:06:18 +0100970 if (version < 1)
971 return 0;
jjako2c381332003-10-21 19:09:53 +0000972
Harald Weltebed35df2011-11-02 13:06:18 +0100973 /* We report back that we support only PDCP PDU headers */
974 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
975 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +0000976
Harald Weltebed35df2011-11-02 13:06:18 +0100977 return gtp_notification(gsn, version, &packet, length,
978 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +0000979}
980
981/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +0100982int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
983 void *pack, unsigned len)
984{
jjako2c381332003-10-21 19:09:53 +0000985
Harald Weltebed35df2011-11-02 13:06:18 +0100986 if (gsn->cb_extheader_ind)
987 gsn->cb_extheader_ind(peer);
988
989 return 0;
jjako2c381332003-10-21 19:09:53 +0000990}
991
jjako52c24142002-12-16 13:33:51 +0000992/* ***********************************************************
993 * Session management messages
994 * Messages: create, update and delete PDP context
995 *
996 * Information storage
997 * Information storage for each PDP context is defined in
998 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
999 * PDP-address (IP address), sequence numbers, charging ID.
1000 * For the SGSN it also includes radio related mobility
1001 * information.
1002 *************************************************************/
1003
Harald Welte7b3347b2010-05-15 12:18:46 +02001004/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001005extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1006 void *cbp)
1007{
1008 union gtp_packet packet;
1009 unsigned int length =
1010 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1011 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001012
Harald Weltebed35df2011-11-02 13:06:18 +01001013 /* TODO: Secondary PDP Context Activation Procedure */
1014 /* In secondary activation procedure the PDP context is identified
1015 by tei in the header. The following fields are omitted: Selection
1016 mode, IMSI, MSISDN, End User Address, Access Point Name and
1017 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001018
Harald Weltebed35df2011-11-02 13:06:18 +01001019 if (pdp->secondary) {
1020 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001021 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001022 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001023 return EOF;
1024 }
1025 }
jjako2c381332003-10-21 19:09:53 +00001026
Harald Weltebed35df2011-11-02 13:06:18 +01001027 if (pdp->version == 0) {
1028 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1029 sizeof(pdp->qos_req0), pdp->qos_req0);
1030 }
jjako52c24142002-12-16 13:33:51 +00001031
Harald Weltebed35df2011-11-02 13:06:18 +01001032 /* Section 7.7.2 */
1033 if (pdp->version == 1) {
1034 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1035 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1036 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1037 }
jjako52c24142002-12-16 13:33:51 +00001038
Harald Weltebed35df2011-11-02 13:06:18 +01001039 /* Section 7.7.3 Routing Area Information */
1040 if (pdp->rai_given == 1)
1041 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1042 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001043
Harald Weltebed35df2011-11-02 13:06:18 +01001044 /* Section 7.7.11 */
1045 if (pdp->norecovery_given == 0)
1046 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1047 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001048
Harald Weltebed35df2011-11-02 13:06:18 +01001049 /* Section 7.7.12 */
1050 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1051 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1052 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001053
Harald Weltebed35df2011-11-02 13:06:18 +01001054 if (pdp->version == 0) {
1055 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1056 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1057 }
jjako08d331d2003-10-13 20:33:30 +00001058
Harald Weltebed35df2011-11-02 13:06:18 +01001059 /* Section 7.7.13 */
1060 if (pdp->version == 1) {
1061 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1062 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001063
Harald Weltebed35df2011-11-02 13:06:18 +01001064 /* Section 7.7.14 */
1065 if (!pdp->teic_confirmed)
1066 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1067 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001068
Harald Weltebed35df2011-11-02 13:06:18 +01001069 /* Section 7.7.17 */
1070 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001071
Harald Weltebed35df2011-11-02 13:06:18 +01001072 /* Section 7.7.17 */
1073 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1074 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1075 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 /* Section 7.7.23 */
1078 if (pdp->cch_pdp) /* Only include charging if flags are set */
1079 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1080 pdp->cch_pdp);
1081 }
jjako9b4971d2004-05-27 20:30:19 +00001082
Harald Weltebed35df2011-11-02 13:06:18 +01001083 /* TODO
1084 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1085 pdp->traceref);
1086 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1087 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001088
Harald Weltebed35df2011-11-02 13:06:18 +01001089 /* Section 7.7.27 */
1090 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1091 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1092 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001093
Harald Weltebed35df2011-11-02 13:06:18 +01001094 /* Section 7.7.30 */
1095 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1096 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1097 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001098
Harald Weltebed35df2011-11-02 13:06:18 +01001099 /* Section 7.7.31 */
1100 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1101 if (pdp->pco_req.l)
1102 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1103 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001104
Harald Weltebed35df2011-11-02 13:06:18 +01001105 /* Section 7.7.32 */
1106 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1107 pdp->gsnlc.l, pdp->gsnlc.v);
1108 /* Section 7.7.32 */
1109 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1110 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 /* Section 7.7.33 */
1113 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1114 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1115 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 /* Section 7.7.34 */
1118 if (pdp->version == 1)
1119 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1120 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001121
Harald Weltebed35df2011-11-02 13:06:18 +01001122 /* Section 7.7.36 */
1123 if ((pdp->version == 1) && pdp->tft.l)
1124 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1125 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001126
Harald Weltebed35df2011-11-02 13:06:18 +01001127 /* Section 7.7.41 */
1128 if ((pdp->version == 1) && pdp->triggerid.l)
1129 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1130 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001131
Harald Weltebed35df2011-11-02 13:06:18 +01001132 /* Section 7.7.42 */
1133 if ((pdp->version == 1) && pdp->omcid.l)
1134 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1135 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001136
Harald Weltebed35df2011-11-02 13:06:18 +01001137 /* new R7 fields */
1138 if (pdp->rattype_given == 1)
1139 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1140 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001141
Harald Weltebed35df2011-11-02 13:06:18 +01001142 if (pdp->userloc_given == 1)
1143 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1144 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001145
Harald Weltebed35df2011-11-02 13:06:18 +01001146 if (pdp->mstz_given == 1)
1147 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1148 pdp->mstz.l, pdp->mstz.v);
1149
1150 if (pdp->imeisv_given == 1)
1151 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1152 pdp->imeisv.l, pdp->imeisv.v);
1153
1154 /* TODO hisaddr0 */
1155 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1156
1157 return 0;
jjako52c24142002-12-16 13:33:51 +00001158}
1159
jjako08d331d2003-10-13 20:33:30 +00001160/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001161int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1162{
jjako08d331d2003-10-13 20:33:30 +00001163
Harald Weltebed35df2011-11-02 13:06:18 +01001164 /* Now send off a reply to the peer */
1165 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1166
1167 if (cause != GTPCAUSE_ACC_REQ) {
1168 pdp_freepdp(pdp);
1169 }
1170
1171 return 0;
jjako08d331d2003-10-13 20:33:30 +00001172}
1173
1174/* API: Register create context indication callback */
1175int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001176 int (*cb_create_context_ind) (struct pdp_t *
1177 pdp))
jjako52c24142002-12-16 13:33:51 +00001178{
Harald Weltebed35df2011-11-02 13:06:18 +01001179 gsn->cb_create_context_ind = cb_create_context_ind;
1180 return 0;
jjako08d331d2003-10-13 20:33:30 +00001181}
1182
jjako08d331d2003-10-13 20:33:30 +00001183/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001184int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1185 uint8_t cause)
1186{
1187 union gtp_packet packet;
1188 unsigned int length =
1189 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001190
Harald Weltebed35df2011-11-02 13:06:18 +01001191 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001192
Harald Weltebed35df2011-11-02 13:06:18 +01001193 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 if (version == 0)
1196 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1197 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001198
Harald Weltebed35df2011-11-02 13:06:18 +01001199 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1200 pdp->reorder);
1201 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1202 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 if (version == 0) {
1205 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1206 pdp->fllu);
1207 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1208 pdp->fllc);
1209 }
jjako08d331d2003-10-13 20:33:30 +00001210
Harald Weltebed35df2011-11-02 13:06:18 +01001211 if (version == 1) {
1212 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1213 pdp->teid_own);
1214 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1215 pdp->teic_own);
1216 }
jjako08d331d2003-10-13 20:33:30 +00001217
Harald Weltebed35df2011-11-02 13:06:18 +01001218 /* TODO: We use teic_own as charging ID */
1219 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1220 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001221
Harald Weltebed35df2011-11-02 13:06:18 +01001222 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1223 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001224
Harald Weltebed35df2011-11-02 13:06:18 +01001225 if (pdp->pco_neg.l) { /* Optional PCO */
1226 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1227 pdp->pco_neg.l, pdp->pco_neg.v);
1228 }
jjako52c24142002-12-16 13:33:51 +00001229
Harald Weltebed35df2011-11-02 13:06:18 +01001230 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1231 pdp->gsnlc.l, pdp->gsnlc.v);
1232 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1233 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001234
Harald Weltebed35df2011-11-02 13:06:18 +01001235 if (version == 1)
1236 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1237 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001238
Harald Weltebed35df2011-11-02 13:06:18 +01001239 /* TODO: Charging gateway address */
1240 }
jjako52c24142002-12-16 13:33:51 +00001241
Harald Weltebed35df2011-11-02 13:06:18 +01001242 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1243 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001244}
1245
1246/* Handle Create PDP Context Request */
1247int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001248 struct sockaddr_in *peer, int fd,
1249 void *pack, unsigned len)
1250{
1251 struct pdp_t *pdp, *pdp_old;
1252 struct pdp_t pdp_buf;
1253 union gtpie_member *ie[GTPIE_SIZE];
1254 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001255
Harald Weltebed35df2011-11-02 13:06:18 +01001256 uint16_t seq = get_seq(pack);
1257 int hlen = get_hlen(pack);
1258 uint8_t linked_nsapi = 0;
1259 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001260
Harald Weltebed35df2011-11-02 13:06:18 +01001261 if (!gtp_dublicate(gsn, version, peer, seq))
1262 return 0;
jjako08d331d2003-10-13 20:33:30 +00001263
Harald Weltebed35df2011-11-02 13:06:18 +01001264 pdp = &pdp_buf;
1265 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001266
Harald Weltebed35df2011-11-02 13:06:18 +01001267 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001268 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1269
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001270 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001271 }
jjako52c24142002-12-16 13:33:51 +00001272
Harald Weltebed35df2011-11-02 13:06:18 +01001273 pdp->seq = seq;
1274 pdp->sa_peer = *peer;
1275 pdp->fd = fd;
1276 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001277
Harald Weltebed35df2011-11-02 13:06:18 +01001278 /* Decode information elements */
1279 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1280 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001281 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1282 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001283 if (0 == version)
1284 return EOF;
1285 else
1286 return gtp_create_pdp_resp(gsn, version, pdp,
1287 GTPCAUSE_INVALID_MESSAGE);
1288 }
jjako52c24142002-12-16 13:33:51 +00001289
Harald Weltebed35df2011-11-02 13:06:18 +01001290 if (version == 1) {
1291 /* Linked NSAPI (conditional) */
1292 /* If included this is the Secondary PDP Context Activation Procedure */
1293 /* In secondary activation IMSI is not included, so the context must be */
1294 /* identified by the tei */
1295 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001296
Harald Weltebed35df2011-11-02 13:06:18 +01001297 /* Find the primary PDP context */
1298 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1299 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001300 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001301 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001302 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001303 return gtp_create_pdp_resp(gsn, version, pdp,
1304 GTPCAUSE_OPT_IE_INCORRECT);
1305 }
jjako2c381332003-10-21 19:09:53 +00001306
Harald Weltebed35df2011-11-02 13:06:18 +01001307 /* Check that the primary PDP context matches linked nsapi */
1308 if (linked_pdp->nsapi != linked_nsapi) {
1309 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001310 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001311 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001312 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001313 return gtp_create_pdp_resp(gsn, version, pdp,
1314 GTPCAUSE_OPT_IE_INCORRECT);
1315 }
jjako52c24142002-12-16 13:33:51 +00001316
Harald Weltebed35df2011-11-02 13:06:18 +01001317 /* Copy parameters from primary context */
1318 pdp->selmode = linked_pdp->selmode;
1319 pdp->imsi = linked_pdp->imsi;
1320 pdp->msisdn = linked_pdp->msisdn;
1321 pdp->eua = linked_pdp->eua;
1322 pdp->pco_req = linked_pdp->pco_req;
1323 pdp->apn_req = linked_pdp->apn_req;
1324 pdp->teic_gn = linked_pdp->teic_gn;
1325 pdp->secondary = 1;
1326 }
1327 }
1328 /* if (version == 1) */
1329 if (version == 0) {
1330 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1331 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1332 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001333 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1334 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001335 return gtp_create_pdp_resp(gsn, version, pdp,
1336 GTPCAUSE_MAN_IE_MISSING);
1337 }
1338 }
jjako08d331d2003-10-13 20:33:30 +00001339
Harald Weltebed35df2011-11-02 13:06:18 +01001340 if ((version == 1) && (!linked_pdp)) {
1341 /* Not Secondary PDP Context Activation Procedure */
1342 /* IMSI (conditional) */
1343 if (gtpie_gettv0
1344 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1345 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001346 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1347 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001348 return gtp_create_pdp_resp(gsn, version, pdp,
1349 GTPCAUSE_MAN_IE_MISSING);
1350 }
1351 }
jjako52c24142002-12-16 13:33:51 +00001352
Harald Weltebed35df2011-11-02 13:06:18 +01001353 /* Recovery (optional) */
1354 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1355 if (gsn->cb_recovery)
1356 gsn->cb_recovery(peer, recovery);
1357 }
jjako52c24142002-12-16 13:33:51 +00001358
Harald Weltebed35df2011-11-02 13:06:18 +01001359 /* Selection mode (conditional) */
1360 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1361 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1362 &pdp->selmode, sizeof(pdp->selmode))) {
1363 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001364 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1365 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001366 return gtp_create_pdp_resp(gsn, version, pdp,
1367 GTPCAUSE_MAN_IE_MISSING);
1368 }
1369 }
jjako52c24142002-12-16 13:33:51 +00001370
Harald Weltebed35df2011-11-02 13:06:18 +01001371 if (version == 0) {
1372 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1373 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001374 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1375 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001376 return gtp_create_pdp_resp(gsn, version, pdp,
1377 GTPCAUSE_MAN_IE_MISSING);
1378 }
jjako52c24142002-12-16 13:33:51 +00001379
Harald Weltebed35df2011-11-02 13:06:18 +01001380 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1381 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001382 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1383 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001384 return gtp_create_pdp_resp(gsn, version, pdp,
1385 GTPCAUSE_MAN_IE_MISSING);
1386 }
1387 }
jjako08d331d2003-10-13 20:33:30 +00001388
Harald Weltebed35df2011-11-02 13:06:18 +01001389 if (version == 1) {
1390 /* TEID (mandatory) */
1391 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1392 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001393 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1394 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001395 return gtp_create_pdp_resp(gsn, version, pdp,
1396 GTPCAUSE_MAN_IE_MISSING);
1397 }
jjako2c381332003-10-21 19:09:53 +00001398
Harald Weltebed35df2011-11-02 13:06:18 +01001399 /* TEIC (conditional) */
1400 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1401 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1402 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001403 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001404 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001405 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001406 return gtp_create_pdp_resp(gsn, version, pdp,
1407 GTPCAUSE_MAN_IE_MISSING);
1408 }
1409 }
jjako08d331d2003-10-13 20:33:30 +00001410
Harald Weltebed35df2011-11-02 13:06:18 +01001411 /* NSAPI (mandatory) */
1412 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1413 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001414 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1415 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001416 return gtp_create_pdp_resp(gsn, version, pdp,
1417 GTPCAUSE_MAN_IE_MISSING);
1418 }
1419 }
jjako2e840a32003-01-28 16:05:18 +00001420
Harald Weltebed35df2011-11-02 13:06:18 +01001421 /* Charging Characteriatics (optional) */
1422 /* Trace reference (optional) */
1423 /* Trace type (optional) */
1424 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001425
Harald Weltebed35df2011-11-02 13:06:18 +01001426 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1427 /* End User Address (conditional) */
1428 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1429 &pdp->eua.v, sizeof(pdp->eua.v))) {
1430 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001431 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1432 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001433 return gtp_create_pdp_resp(gsn, version, pdp,
1434 GTPCAUSE_MAN_IE_MISSING);
1435 }
jjako08d331d2003-10-13 20:33:30 +00001436
Harald Weltebed35df2011-11-02 13:06:18 +01001437 /* APN */
1438 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1439 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1440 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001441 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1442 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001443 return gtp_create_pdp_resp(gsn, version, pdp,
1444 GTPCAUSE_MAN_IE_MISSING);
1445 }
jjako2c381332003-10-21 19:09:53 +00001446
Harald Weltebed35df2011-11-02 13:06:18 +01001447 /* Extract protocol configuration options (optional) */
1448 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1449 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1450 }
1451 }
jjako2c381332003-10-21 19:09:53 +00001452
Harald Weltebed35df2011-11-02 13:06:18 +01001453 /* SGSN address for signalling (mandatory) */
1454 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1455 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1456 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001457 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1458 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001459 return gtp_create_pdp_resp(gsn, version, pdp,
1460 GTPCAUSE_MAN_IE_MISSING);
1461 }
jjako2e840a32003-01-28 16:05:18 +00001462
Harald Weltebed35df2011-11-02 13:06:18 +01001463 /* SGSN address for user traffic (mandatory) */
1464 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1465 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1466 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001467 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1468 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001469 return gtp_create_pdp_resp(gsn, version, pdp,
1470 GTPCAUSE_MAN_IE_MISSING);
1471 }
jjako52c24142002-12-16 13:33:51 +00001472
Harald Weltebed35df2011-11-02 13:06:18 +01001473 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1474 /* MSISDN (conditional) */
1475 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1476 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1477 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001478 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1479 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001480 return gtp_create_pdp_resp(gsn, version, pdp,
1481 GTPCAUSE_MAN_IE_MISSING);
1482 }
1483 }
jjako52c24142002-12-16 13:33:51 +00001484
Harald Weltebed35df2011-11-02 13:06:18 +01001485 if (version == 1) {
1486 /* QoS (mandatory) */
1487 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1488 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1489 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001490 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1491 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001492 return gtp_create_pdp_resp(gsn, version, pdp,
1493 GTPCAUSE_MAN_IE_MISSING);
1494 }
1495
1496 /* TFT (conditional) */
1497 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1498 &pdp->tft.v, sizeof(pdp->tft.v))) {
1499 }
1500
1501 /* Trigger ID */
1502 /* OMC identity */
1503 }
1504
1505 /* Initialize our own IP addresses */
1506 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1507 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1508
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001509 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001510
1511 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1512 /* Found old pdp with same tid. Now the voodoo begins! */
1513 /* 09.60 / 29.060 allows create on existing context to "steal" */
1514 /* the context which was allready established */
1515 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001516 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001517 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1518 &&
1519 (!memcmp
1520 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1521 && (pdp->selmode == pdp_old->selmode)
1522 && (pdp->msisdn.l == pdp_old->msisdn.l)
1523 &&
1524 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1525 {
1526 /* OK! We are dealing with the same APN. We will copy new
1527 * parameters to the old pdp and send off confirmation
1528 * We ignore the following information elements:
1529 * QoS: MS will get originally negotiated QoS.
1530 * End user address (EUA). MS will get old EUA anyway.
1531 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001532 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001533
1534 /* Copy remote flow label */
1535 pdp_old->flru = pdp->flru;
1536 pdp_old->flrc = pdp->flrc;
1537
1538 /* Copy remote tei */
1539 pdp_old->teid_gn = pdp->teid_gn;
1540 pdp_old->teic_gn = pdp->teic_gn;
1541
1542 /* Copy peer GSN address */
1543 pdp_old->gsnrc.l = pdp->gsnrc.l;
1544 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1545 pdp_old->gsnru.l = pdp->gsnru.l;
1546 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1547
1548 /* Copy request parameters */
1549 pdp_old->seq = pdp->seq;
1550 pdp_old->sa_peer = pdp->sa_peer;
1551 pdp_old->fd = pdp->fd = fd;
1552 pdp_old->version = pdp->version = version;
1553
1554 /* Switch to using the old pdp context */
1555 pdp = pdp_old;
1556
1557 /* Confirm to peer that things were "successful" */
1558 return gtp_create_pdp_resp(gsn, version, pdp,
1559 GTPCAUSE_ACC_REQ);
1560 } else { /* This is not the same PDP context. Delete the old one. */
1561
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001562 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001563
1564 if (gsn->cb_delete_context)
1565 gsn->cb_delete_context(pdp_old);
1566 pdp_freepdp(pdp_old);
1567
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001568 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001569 }
1570 }
1571
1572 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1573
1574 /* Callback function to validata login */
1575 if (gsn->cb_create_context_ind != 0)
1576 return gsn->cb_create_context_ind(pdp);
1577 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001578 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1579 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001580 return gtp_create_pdp_resp(gsn, version, pdp,
1581 GTPCAUSE_NOT_SUPPORTED);
1582 }
jjako52c24142002-12-16 13:33:51 +00001583}
1584
jjako52c24142002-12-16 13:33:51 +00001585/* Handle Create PDP Context Response */
1586int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001587 struct sockaddr_in *peer, void *pack, unsigned len)
1588{
1589 struct pdp_t *pdp;
1590 union gtpie_member *ie[GTPIE_SIZE];
1591 uint8_t cause, recovery;
1592 void *cbp = NULL;
1593 uint8_t type = 0;
1594 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001595
Harald Weltebed35df2011-11-02 13:06:18 +01001596 /* Remove packet from queue */
1597 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1598 return EOF;
jjako52c24142002-12-16 13:33:51 +00001599
Harald Weltebed35df2011-11-02 13:06:18 +01001600 /* Find the context in question */
1601 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1602 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001603 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001604 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001605 if (gsn->cb_conf)
1606 gsn->cb_conf(type, EOF, NULL, cbp);
1607 return EOF;
1608 }
jjako2c381332003-10-21 19:09:53 +00001609
Harald Weltebed35df2011-11-02 13:06:18 +01001610 /* Register that we have received a valid teic from GGSN */
1611 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001612
Harald Weltebed35df2011-11-02 13:06:18 +01001613 /* Decode information elements */
1614 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1615 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001616 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1617 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001618 if (gsn->cb_conf)
1619 gsn->cb_conf(type, EOF, pdp, cbp);
1620 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1621 pdp_freepdp(pdp); */
1622 return EOF;
1623 }
jjako52c24142002-12-16 13:33:51 +00001624
Harald Weltebed35df2011-11-02 13:06:18 +01001625 /* Extract cause value (mandatory) */
1626 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1627 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001628 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1629 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001630 if (gsn->cb_conf)
1631 gsn->cb_conf(type, EOF, pdp, cbp);
1632 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1633 pdp_freepdp(pdp); */
1634 return EOF;
1635 }
jjako52c24142002-12-16 13:33:51 +00001636
Harald Weltebed35df2011-11-02 13:06:18 +01001637 /* Extract recovery (optional) */
1638 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1639 if (gsn->cb_recovery)
1640 gsn->cb_recovery(peer, recovery);
1641 }
jjako52c24142002-12-16 13:33:51 +00001642
Harald Weltebed35df2011-11-02 13:06:18 +01001643 /* Extract protocol configuration options (optional) */
1644 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1645 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1646 }
jjako52c24142002-12-16 13:33:51 +00001647
Harald Weltebed35df2011-11-02 13:06:18 +01001648 /* Check all conditional information elements */
1649 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001650
Harald Weltebed35df2011-11-02 13:06:18 +01001651 if (version == 0) {
1652 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1653 &pdp->qos_neg0,
1654 sizeof(pdp->qos_neg0))) {
1655 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001656 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001657 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001658 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001659 if (gsn->cb_conf)
1660 gsn->cb_conf(type, EOF, pdp, cbp);
1661 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1662 pdp_freepdp(pdp); */
1663 return EOF;
1664 }
1665 }
jjako08d331d2003-10-13 20:33:30 +00001666
Harald Weltebed35df2011-11-02 13:06:18 +01001667 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1668 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001669 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001670 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001671 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001672 if (gsn->cb_conf)
1673 gsn->cb_conf(type, EOF, pdp, cbp);
1674 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1675 pdp_freepdp(pdp); */
1676 return EOF;
1677 }
jjako52c24142002-12-16 13:33:51 +00001678
Harald Weltebed35df2011-11-02 13:06:18 +01001679 if (version == 0) {
1680 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1681 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001682 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001683 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001684 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001685 if (gsn->cb_conf)
1686 gsn->cb_conf(type, EOF, pdp, cbp);
1687 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1688 pdp_freepdp(pdp); */
1689 return EOF;
1690 }
jjako52c24142002-12-16 13:33:51 +00001691
Harald Weltebed35df2011-11-02 13:06:18 +01001692 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1693 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001694 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001695 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001696 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001697 if (gsn->cb_conf)
1698 gsn->cb_conf(type, EOF, pdp, cbp);
1699 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1700 pdp_freepdp(pdp); */
1701 return EOF;
1702 }
1703 }
1704
1705 if (version == 1) {
1706 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1707 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001708 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001709 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001710 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001711 if (gsn->cb_conf)
1712 gsn->cb_conf(type, EOF, pdp, cbp);
1713 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1714 pdp_freepdp(pdp); */
1715 return EOF;
1716 }
1717
1718 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1719 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001720 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001721 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001722 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001723 if (gsn->cb_conf)
1724 gsn->cb_conf(type, EOF, pdp, cbp);
1725 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1726 pdp_freepdp(pdp); */
1727 return EOF;
1728 }
1729 }
1730
1731 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1732 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001733 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001734 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001735 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001736 if (gsn->cb_conf)
1737 gsn->cb_conf(type, EOF, pdp, cbp);
1738 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1739 pdp_freepdp(pdp); */
1740 }
1741
1742 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1743 &pdp->eua.v, sizeof(pdp->eua.v))) {
1744 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001745 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001746 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001747 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001748 if (gsn->cb_conf)
1749 gsn->cb_conf(type, EOF, pdp, cbp);
1750 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1751 pdp_freepdp(pdp); */
1752 return EOF;
1753 }
1754
1755 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1756 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1757 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001758 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001759 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001760 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001761 if (gsn->cb_conf)
1762 gsn->cb_conf(type, EOF, pdp, cbp);
1763 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1764 pdp_freepdp(pdp); */
1765 return EOF;
1766 }
1767
1768 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1769 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1770 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001771 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001772 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001773 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001774 if (gsn->cb_conf)
1775 gsn->cb_conf(type, EOF, pdp, cbp);
1776 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1777 pdp_freepdp(pdp); */
1778 return EOF;
1779 }
1780
1781 if (version == 1) {
1782 if (gtpie_gettlv
1783 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1784 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1785 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001786 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001787 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001788 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001789 if (gsn->cb_conf)
1790 gsn->cb_conf(type, EOF, pdp, cbp);
1791 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1792 pdp_freepdp(pdp); */
1793 return EOF;
1794 }
1795 }
1796
1797 }
1798
1799 if (gsn->cb_conf)
1800 gsn->cb_conf(type, cause, pdp, cbp);
1801
1802 return 0;
jjako52c24142002-12-16 13:33:51 +00001803}
1804
jjako08d331d2003-10-13 20:33:30 +00001805/* API: Send Update PDP Context Request */
1806int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001807 struct in_addr *inetaddr)
1808{
1809 union gtp_packet packet;
1810 unsigned int length =
1811 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001812
Harald Weltebed35df2011-11-02 13:06:18 +01001813 if (pdp->version == 0)
1814 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1815 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001816
Harald Weltebed35df2011-11-02 13:06:18 +01001817 /* Include IMSI if updating with unknown teic_gn */
1818 if ((pdp->version == 1) && (!pdp->teic_gn))
1819 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1820 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1821
1822 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1823 gsn->restart_counter);
1824
1825 if (pdp->version == 0) {
1826 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1827 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1828 }
1829
1830 if (pdp->version == 1) {
1831 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1832 pdp->teid_own);
1833
1834 if (!pdp->teic_confirmed)
1835 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1836 pdp->teic_own);
1837 }
1838
1839 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1840
1841 /* TODO
1842 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1843 pdp->traceref);
1844 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1845 pdp->tracetype); */
1846
1847 /* TODO if ggsn update message
1848 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1849 pdp->eua.l, pdp->eua.v);
1850 */
1851
1852 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1853 pdp->gsnlc.l, pdp->gsnlc.v);
1854 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1855 pdp->gsnlu.l, pdp->gsnlu.v);
1856
1857 if (pdp->version == 1)
1858 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1859 pdp->qos_req.l, pdp->qos_req.v);
1860
1861 if ((pdp->version == 1) && pdp->tft.l)
1862 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1863 pdp->tft.l, pdp->tft.v);
1864
1865 if ((pdp->version == 1) && pdp->triggerid.l)
1866 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1867 pdp->triggerid.l, pdp->triggerid.v);
1868
1869 if ((pdp->version == 1) && pdp->omcid.l)
1870 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1871 pdp->omcid.l, pdp->omcid.v);
1872
1873 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1874
1875 return 0;
jjako52c24142002-12-16 13:33:51 +00001876}
1877
jjako08d331d2003-10-13 20:33:30 +00001878/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001879int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1880 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001881 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001882 struct pdp_t *pdp, uint8_t cause)
1883{
jjako08d331d2003-10-13 20:33:30 +00001884
Harald Weltebed35df2011-11-02 13:06:18 +01001885 union gtp_packet packet;
1886 unsigned int length =
1887 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001888
Harald Weltebed35df2011-11-02 13:06:18 +01001889 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001890
Harald Weltebed35df2011-11-02 13:06:18 +01001891 if (cause == GTPCAUSE_ACC_REQ) {
1892
1893 if (version == 0)
1894 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1895 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1896
1897 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1898 gsn->restart_counter);
1899
1900 if (version == 0) {
1901 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1902 pdp->fllu);
1903 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1904 pdp->fllc);
1905 }
1906
1907 if (version == 1) {
1908 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1909 pdp->teid_own);
1910
1911 if (!pdp->teic_confirmed)
1912 gtpie_tv4(&packet, &length, GTP_MAX,
1913 GTPIE_TEI_C, pdp->teic_own);
1914 }
1915
1916 /* TODO we use teid_own as charging ID address */
1917 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1918 pdp->teid_own);
1919
1920 /* If ggsn
1921 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1922 pdp->eua.l, pdp->eua.v); */
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 (version == 1)
1930 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1931 pdp->qos_neg.l, pdp->qos_neg.v);
1932
1933 /* TODO: Charging gateway address */
1934 }
1935
1936 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1937 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001938}
1939
jjako52c24142002-12-16 13:33:51 +00001940/* Handle Update PDP Context Request */
1941int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001942 struct sockaddr_in *peer, int fd,
1943 void *pack, unsigned len)
1944{
1945 struct pdp_t *pdp;
1946 struct pdp_t pdp_backup;
1947 union gtpie_member *ie[GTPIE_SIZE];
1948 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001949
Harald Weltebed35df2011-11-02 13:06:18 +01001950 uint16_t seq = get_seq(pack);
1951 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001952
Harald Weltebed35df2011-11-02 13:06:18 +01001953 uint64_t imsi;
1954 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00001955
Harald Weltebed35df2011-11-02 13:06:18 +01001956 /* Is this a dublicate ? */
1957 if (!gtp_dublicate(gsn, version, peer, seq)) {
1958 return 0; /* We allready send of response once */
1959 }
jjako08d331d2003-10-13 20:33:30 +00001960
Harald Weltebed35df2011-11-02 13:06:18 +01001961 /* Decode information elements */
1962 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1963 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001964 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1965 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001966 if (0 == version)
1967 return EOF;
1968 else
1969 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1970 len, NULL,
1971 GTPCAUSE_INVALID_MESSAGE);
1972 }
jjako08d331d2003-10-13 20:33:30 +00001973
Harald Weltebed35df2011-11-02 13:06:18 +01001974 /* Finding PDP: */
1975 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1976 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1977 /* we have to use the tunnel endpoint identifier */
1978 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001979 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1980
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001981 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00001982
Harald Weltebed35df2011-11-02 13:06:18 +01001983 /* Find the context in question */
1984 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1985 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001986 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1987 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001988 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1989 len, NULL,
1990 GTPCAUSE_NON_EXIST);
1991 }
1992 } else if (version == 1) {
1993 /* NSAPI (mandatory) */
1994 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
1995 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001996 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1997 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001998 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
1999 len, NULL,
2000 GTPCAUSE_MAN_IE_MISSING);
2001 }
jjako08d331d2003-10-13 20:33:30 +00002002
Harald Weltebed35df2011-11-02 13:06:18 +01002003 /* IMSI (conditional) */
2004 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2005 /* Find the context in question */
2006 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2007 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002008 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002009 pack, len, "Unknown PDP context: %u\n",
2010 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002011 return gtp_update_pdp_resp(gsn, version, peer,
2012 fd, pack, len, NULL,
2013 GTPCAUSE_NON_EXIST);
2014 }
2015 } else {
2016 /* Find the context in question */
2017 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2018 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002019 GTP_LOGPKG(LOGL_ERROR, peer,
2020 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002021 return gtp_update_pdp_resp(gsn, version, peer,
2022 fd, pack, len, NULL,
2023 GTPCAUSE_NON_EXIST);
2024 }
2025 }
2026 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002027 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002028 return EOF;
2029 }
jjako08d331d2003-10-13 20:33:30 +00002030
Harald Weltebed35df2011-11-02 13:06:18 +01002031 /* Make a backup copy in case anything is wrong */
2032 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002033
Harald Weltebed35df2011-11-02 13:06:18 +01002034 if (version == 0) {
2035 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2036 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2037 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002038 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2039 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002040 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2041 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2042 len, pdp,
2043 GTPCAUSE_MAN_IE_MISSING);
2044 }
2045 }
jjako52c24142002-12-16 13:33:51 +00002046
Harald Weltebed35df2011-11-02 13:06:18 +01002047 /* Recovery (optional) */
2048 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2049 if (gsn->cb_recovery)
2050 gsn->cb_recovery(peer, recovery);
2051 }
jjako08d331d2003-10-13 20:33:30 +00002052
Harald Weltebed35df2011-11-02 13:06:18 +01002053 if (version == 0) {
2054 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2055 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002056 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2057 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002058 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2059 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2060 len, pdp,
2061 GTPCAUSE_MAN_IE_MISSING);
2062 }
jjako52c24142002-12-16 13:33:51 +00002063
Harald Weltebed35df2011-11-02 13:06:18 +01002064 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2065 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002066 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2067 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002068 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2069 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2070 len, pdp,
2071 GTPCAUSE_MAN_IE_MISSING);
2072 }
2073 }
jjako52c24142002-12-16 13:33:51 +00002074
Harald Weltebed35df2011-11-02 13:06:18 +01002075 if (version == 1) {
2076 /* TEID (mandatory) */
2077 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2078 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002079 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2080 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002081 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2082 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2083 len, pdp,
2084 GTPCAUSE_MAN_IE_MISSING);
2085 }
jjako52c24142002-12-16 13:33:51 +00002086
Harald Weltebed35df2011-11-02 13:06:18 +01002087 /* TEIC (conditional) */
2088 /* If TEIC is not included it means that we have allready received it */
2089 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2090 /* all updated contexts, or only for one of the linked contexts */
2091 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2092
2093 /* NSAPI (mandatory) */
2094 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2095 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002096 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2097 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002098 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2099 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2100 len, pdp,
2101 GTPCAUSE_MAN_IE_MISSING);
2102 }
2103 }
2104
2105 /* Trace reference (optional) */
2106 /* Trace type (optional) */
2107
2108 /* End User Address (conditional) TODO: GGSN Initiated
2109 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2110 &pdp->eua.v, sizeof(pdp->eua.v))) {
2111 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002112 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002113 "Missing mandatory information field");
2114 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2115 return gtp_update_pdp_resp(gsn, version, pdp,
2116 GTPCAUSE_MAN_IE_MISSING);
2117 } */
2118
2119 /* SGSN address for signalling (mandatory) */
2120 /* It is weird that this is mandatory when TEIC is conditional */
2121 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2122 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2123 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002124 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2125 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002126 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2127 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2128 pdp, GTPCAUSE_MAN_IE_MISSING);
2129 }
2130
2131 /* SGSN address for user traffic (mandatory) */
2132 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2133 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2134 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002135 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2136 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002137 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2138 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2139 pdp, GTPCAUSE_MAN_IE_MISSING);
2140 }
2141
2142 if (version == 1) {
2143 /* QoS (mandatory) */
2144 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2145 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2146 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002147 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2148 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002149 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2150 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2151 len, pdp,
2152 GTPCAUSE_MAN_IE_MISSING);
2153 }
2154
2155 /* TFT (conditional) */
2156 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2157 &pdp->tft.v, sizeof(pdp->tft.v))) {
2158 }
2159
2160 /* OMC identity */
2161 }
2162
2163 /* Confirm to peer that things were "successful" */
2164 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2165 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002166}
2167
jjako52c24142002-12-16 13:33:51 +00002168/* Handle Update PDP Context Response */
2169int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002170 struct sockaddr_in *peer, void *pack, unsigned len)
2171{
2172 struct pdp_t *pdp;
2173 union gtpie_member *ie[GTPIE_SIZE];
2174 uint8_t cause, recovery;
2175 void *cbp = NULL;
2176 uint8_t type = 0;
jjako52c24142002-12-16 13:33:51 +00002177
Harald Weltebed35df2011-11-02 13:06:18 +01002178 /* Remove packet from queue */
2179 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2180 return EOF;
jjako52c24142002-12-16 13:33:51 +00002181
Harald Weltebed35df2011-11-02 13:06:18 +01002182 /* Find the context in question */
2183 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2184 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002185 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2186 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002187 if (gsn->cb_conf)
2188 gsn->cb_conf(type, cause, NULL, cbp);
2189 return EOF;
2190 }
jjako2c381332003-10-21 19:09:53 +00002191
Harald Weltebed35df2011-11-02 13:06:18 +01002192 /* Register that we have received a valid teic from GGSN */
2193 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002194
Harald Weltebed35df2011-11-02 13:06:18 +01002195 /* Decode information elements */
2196 if (gtpie_decaps
2197 (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
2198 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002199 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2200 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002201 if (gsn->cb_conf)
2202 gsn->cb_conf(type, EOF, pdp, cbp);
2203 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2204 pdp_freepdp(pdp); */
2205 return EOF;
2206 }
jjako52c24142002-12-16 13:33:51 +00002207
Harald Weltebed35df2011-11-02 13:06:18 +01002208 /* Extract cause value (mandatory) */
2209 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2210 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002211 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2212 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002213 if (gsn->cb_conf)
2214 gsn->cb_conf(type, EOF, pdp, cbp);
2215 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2216 pdp_freepdp(pdp); */
2217 return EOF;
2218 }
jjako52c24142002-12-16 13:33:51 +00002219
Harald Weltebed35df2011-11-02 13:06:18 +01002220 /* Extract recovery (optional) */
2221 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2222 if (gsn->cb_recovery)
2223 gsn->cb_recovery(peer, recovery);
2224 }
2225
2226 /* Check all conditional information elements */
2227 if (GTPCAUSE_ACC_REQ != cause) {
2228 if (gsn->cb_conf)
2229 gsn->cb_conf(type, cause, pdp, cbp);
2230 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2231 pdp_freepdp(pdp); */
2232 return 0;
2233 } else {
2234 /* Check for missing conditionary information elements */
2235 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2236 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2237 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2238 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2239 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2240 gtpie_exist(ie, GTPIE_EUA, 0) &&
2241 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2242 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2243 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002244 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01002245 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002246 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002247 if (gsn->cb_conf)
2248 gsn->cb_conf(type, EOF, pdp, cbp);
2249 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2250 pdp_freepdp(pdp); */
2251 return EOF;
2252 }
2253
2254 /* Update pdp with new values */
2255 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2256 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2257 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2258 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2259 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2260 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2261 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2262 &pdp->eua.v, sizeof(pdp->eua.v));
2263 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2264 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2265 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2266 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2267
2268 if (gsn->cb_conf)
2269 gsn->cb_conf(type, cause, pdp, cbp);
2270 return 0; /* Succes */
2271 }
jjako52c24142002-12-16 13:33:51 +00002272}
2273
jjako08d331d2003-10-13 20:33:30 +00002274/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002275int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002276 int teardown)
2277{
2278 union gtp_packet packet;
2279 unsigned int length =
2280 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2281 struct in_addr addr;
2282 struct pdp_t *linked_pdp;
2283 struct pdp_t *secondary_pdp;
2284 int n;
2285 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002286
Harald Weltebed35df2011-11-02 13:06:18 +01002287 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2288 gsn->err_address++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002289 LOGP(DLGTP, LOGL_ERROR,
2290 "GSN address conversion failed\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002291 return EOF;
jjako2c381332003-10-21 19:09:53 +00002292 }
jjako2c381332003-10-21 19:09:53 +00002293
Harald Weltebed35df2011-11-02 13:06:18 +01002294 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002295 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002296 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002297 return EOF;
2298 }
2299
2300 if (!teardown) {
2301 for (n = 0; n < PDP_MAXNSAPI; n++)
2302 if (linked_pdp->secondary_tei[n])
2303 count++;
2304 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002305 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002306 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002307 return EOF;
2308 }
2309 }
2310
2311 if (pdp->version == 1) {
2312 if (teardown)
2313 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2314 0xff);
2315
2316 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2317 }
2318
2319 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2320
2321 if (teardown) { /* Remove all contexts */
2322 for (n = 0; n < PDP_MAXNSAPI; n++) {
2323 if (linked_pdp->secondary_tei[n]) {
2324 if (pdp_getgtp1
2325 (&secondary_pdp,
2326 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002327 LOGP(DLGTP, LOGL_ERROR,
2328 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002329 return EOF;
2330 }
2331 if (linked_pdp != secondary_pdp) {
2332 if (gsn->cb_delete_context)
2333 gsn->cb_delete_context
2334 (secondary_pdp);
2335 pdp_freepdp(secondary_pdp);
2336 }
2337 }
2338 }
2339 if (gsn->cb_delete_context)
2340 gsn->cb_delete_context(linked_pdp);
2341 pdp_freepdp(linked_pdp);
2342 } else {
2343 if (gsn->cb_delete_context)
2344 gsn->cb_delete_context(pdp);
2345 if (pdp == linked_pdp) {
2346 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2347 linked_pdp->nodata = 1;
2348 } else
2349 pdp_freepdp(pdp);
2350 }
2351
2352 return 0;
jjako2c381332003-10-21 19:09:53 +00002353}
jjako08d331d2003-10-13 20:33:30 +00002354
jjako52c24142002-12-16 13:33:51 +00002355/* Send Delete PDP Context Response */
2356int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002357 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002358 void *pack, unsigned len,
2359 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002360 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002361{
Harald Weltebed35df2011-11-02 13:06:18 +01002362 union gtp_packet packet;
2363 struct pdp_t *secondary_pdp;
2364 unsigned int length =
2365 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2366 int n;
jjako52c24142002-12-16 13:33:51 +00002367
Harald Weltebed35df2011-11-02 13:06:18 +01002368 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002369
Harald Weltebed35df2011-11-02 13:06:18 +01002370 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2371 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002372
Harald Weltebed35df2011-11-02 13:06:18 +01002373 if (cause == GTPCAUSE_ACC_REQ) {
2374 if ((teardown) || (version == 0)) { /* Remove all contexts */
2375 for (n = 0; n < PDP_MAXNSAPI; n++) {
2376 if (linked_pdp->secondary_tei[n]) {
2377 if (pdp_getgtp1
2378 (&secondary_pdp,
2379 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002380 LOGP(DLGTP, LOGL_ERROR,
2381 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002382 return EOF;
2383 }
2384 if (linked_pdp != secondary_pdp) {
2385 if (gsn->cb_delete_context)
2386 gsn->cb_delete_context
2387 (secondary_pdp);
2388 pdp_freepdp(secondary_pdp);
2389 }
2390 }
2391 }
2392 if (gsn->cb_delete_context)
2393 gsn->cb_delete_context(linked_pdp);
2394 pdp_freepdp(linked_pdp);
2395 } else { /* Remove only current context */
2396 if (gsn->cb_delete_context)
2397 gsn->cb_delete_context(pdp);
2398 if (pdp == linked_pdp) {
2399 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2400 0;
2401 linked_pdp->nodata = 1;
2402 } else
2403 pdp_freepdp(pdp);
2404 }
jjako2c381332003-10-21 19:09:53 +00002405 }
Harald Weltebed35df2011-11-02 13:06:18 +01002406 /* if (cause == GTPCAUSE_ACC_REQ) */
2407 return 0;
jjako52c24142002-12-16 13:33:51 +00002408}
2409
2410/* Handle Delete PDP Context Request */
2411int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002412 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002413 void *pack, unsigned len)
2414{
2415 struct pdp_t *pdp = NULL;
2416 struct pdp_t *linked_pdp = NULL;
2417 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002418
Harald Weltebed35df2011-11-02 13:06:18 +01002419 uint16_t seq = get_seq(pack);
2420 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002421
Harald Weltebed35df2011-11-02 13:06:18 +01002422 uint8_t nsapi;
2423 uint8_t teardown = 0;
2424 int n;
2425 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002426
Harald Weltebed35df2011-11-02 13:06:18 +01002427 /* Is this a dublicate ? */
2428 if (!gtp_dublicate(gsn, version, peer, seq)) {
2429 return 0; /* We allready send off response once */
2430 }
jjako2c381332003-10-21 19:09:53 +00002431
Harald Weltebed35df2011-11-02 13:06:18 +01002432 /* Find the linked context in question */
2433 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2434 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002435 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002436 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002437 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2438 NULL, NULL, GTPCAUSE_NON_EXIST,
2439 teardown);
2440 }
jjako2c381332003-10-21 19:09:53 +00002441
Harald Weltebed35df2011-11-02 13:06:18 +01002442 /* If version 0 this is also the secondary context */
2443 if (version == 0)
2444 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002445
Harald Weltebed35df2011-11-02 13:06:18 +01002446 /* Decode information elements */
2447 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2448 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002449 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2450 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002451 if (0 == version)
2452 return EOF;
2453 else
2454 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2455 len, NULL, NULL,
2456 GTPCAUSE_INVALID_MESSAGE,
2457 teardown);
2458 }
2459
2460 if (version == 1) {
2461 /* NSAPI (mandatory) */
2462 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2463 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002464 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2465 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002466 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2467 len, NULL, NULL,
2468 GTPCAUSE_MAN_IE_MISSING,
2469 teardown);
2470 }
2471
2472 /* Find the context in question */
2473 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2474 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002475 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2476 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002477 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2478 len, NULL, NULL,
2479 GTPCAUSE_NON_EXIST,
2480 teardown);
2481 }
2482
2483 /* Teardown (conditional) */
2484 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2485
2486 if (!teardown) {
2487 for (n = 0; n < PDP_MAXNSAPI; n++)
2488 if (linked_pdp->secondary_tei[n])
2489 count++;
2490 if (count <= 1) {
2491 return 0; /* 29.060 7.3.5 Ignore message */
2492 }
2493 }
2494 }
2495
2496 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2497 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002498}
2499
jjako52c24142002-12-16 13:33:51 +00002500/* Handle Delete PDP Context Response */
2501int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002502 struct sockaddr_in *peer, void *pack, unsigned len)
2503{
2504 union gtpie_member *ie[GTPIE_SIZE];
2505 uint8_t cause;
2506 void *cbp = NULL;
2507 uint8_t type = 0;
2508 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002509
Harald Weltebed35df2011-11-02 13:06:18 +01002510 /* Remove packet from queue */
2511 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2512 return EOF;
jjako52c24142002-12-16 13:33:51 +00002513
Harald Weltebed35df2011-11-02 13:06:18 +01002514 /* Decode information elements */
2515 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2516 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002517 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2518 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002519 if (gsn->cb_conf)
2520 gsn->cb_conf(type, EOF, NULL, cbp);
2521 return EOF;
2522 }
2523
2524 /* Extract cause value (mandatory) */
2525 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2526 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002527 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2528 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002529 if (gsn->cb_conf)
2530 gsn->cb_conf(type, EOF, NULL, cbp);
2531 return EOF;
2532 }
2533
2534 /* Check the cause value (again) */
2535 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2536 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002537 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2538 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002539 if (gsn->cb_conf)
2540 gsn->cb_conf(type, cause, NULL, cbp);
2541 return EOF;
2542 }
2543
2544 /* Callback function to notify application */
2545 if (gsn->cb_conf)
2546 gsn->cb_conf(type, cause, NULL, cbp);
2547
2548 return 0;
jjako52c24142002-12-16 13:33:51 +00002549}
2550
2551/* Send Error Indication (response to a GPDU message */
2552int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002553 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002554 void *pack, unsigned len)
2555{
Harald Weltebed35df2011-11-02 13:06:18 +01002556 union gtp_packet packet;
2557 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2558
2559 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2560 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002561}
2562
2563/* Handle Error Indication */
2564int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002565 struct sockaddr_in *peer, void *pack, unsigned len)
2566{
2567 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002568
Harald Weltebed35df2011-11-02 13:06:18 +01002569 /* Find the context in question */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002570 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002571 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002572 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2573 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002574 return EOF;
2575 }
jjako52c24142002-12-16 13:33:51 +00002576
Harald Weltebed35df2011-11-02 13:06:18 +01002577 gsn->err_unknownpdp++; /* TODO: Change counter */
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002578 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2579 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002580
2581 if (gsn->cb_delete_context)
2582 gsn->cb_delete_context(pdp);
2583 pdp_freepdp(pdp);
2584 return 0;
jjako52c24142002-12-16 13:33:51 +00002585}
2586
2587int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002588 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2589{
jjako08d331d2003-10-13 20:33:30 +00002590
Harald Weltebed35df2011-11-02 13:06:18 +01002591 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002592
Harald Weltebed35df2011-11-02 13:06:18 +01002593 /* Need to include code to verify packet src and dest addresses */
2594 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002595
Harald Weltebed35df2011-11-02 13:06:18 +01002596 if (version == 0) {
2597 if (pdp_getgtp0
2598 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2599 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002600 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2601 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002602 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2603 len);
2604 }
2605 hlen = GTP0_HEADER_SIZE;
2606 } else if (version == 1) {
2607 if (pdp_getgtp1
2608 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2609 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002610 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2611 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002612 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2613 len);
2614 }
jjako08d331d2003-10-13 20:33:30 +00002615
Harald Weltebed35df2011-11-02 13:06:18 +01002616 /* Is this a long or a short header ? */
2617 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2618 hlen = GTP1_HEADER_SIZE_LONG;
2619 else
2620 hlen = GTP1_HEADER_SIZE_SHORT;
2621 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002622 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002623 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002624 }
jjako08d331d2003-10-13 20:33:30 +00002625
Harald Weltebed35df2011-11-02 13:06:18 +01002626 /* If the GPDU was not from the peer GSN tell him to delete context */
2627 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2628 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002629 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2630 "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002631 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2632 }
jjako52c24142002-12-16 13:33:51 +00002633
Harald Weltebed35df2011-11-02 13:06:18 +01002634 /* Callback function */
2635 if (gsn->cb_data_ind != 0)
2636 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2637
2638 return 0;
jjako52c24142002-12-16 13:33:51 +00002639}
2640
jjako52c24142002-12-16 13:33:51 +00002641/* Receives GTP packet and sends off for further processing
2642 * Function will check the validity of the header. If the header
2643 * is not valid the packet is either dropped or a version not
2644 * supported is returned to the peer.
2645 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002646int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002647{
Harald Weltebed35df2011-11-02 13:06:18 +01002648 unsigned char buffer[PACKET_MAX];
2649 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002650 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002651 int status;
2652 struct gtp0_header *pheader;
2653 int version = 0; /* GTP version should be determined from header! */
2654 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002655
Harald Weltebed35df2011-11-02 13:06:18 +01002656 /* TODO: Need strategy of userspace buffering and blocking */
2657 /* Currently read is non-blocking and send is blocking. */
2658 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002659
Harald Weltebed35df2011-11-02 13:06:18 +01002660 while (1) { /* Loop until no more to read */
2661 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002662 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002663 return -1;
2664 }
2665 peerlen = sizeof(peer);
2666 if ((status =
2667 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2668 (struct sockaddr *)&peer, &peerlen)) < 0) {
2669 if (errno == EAGAIN)
2670 return 0;
2671 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002672 LOGP(DLGTP, LOGL_ERROR,
2673 "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002674 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2675 status, status ? strerror(errno) : "No error");
2676 return -1;
2677 }
jjako1db1c812003-07-06 20:53:57 +00002678
Harald Weltebed35df2011-11-02 13:06:18 +01002679 /* Need at least 1 byte in order to check version */
2680 if (status < (1)) {
2681 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002682 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2683 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002684 continue;
2685 }
jjako08d331d2003-10-13 20:33:30 +00002686
Harald Weltebed35df2011-11-02 13:06:18 +01002687 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002688
Harald Weltebed35df2011-11-02 13:06:18 +01002689 /* Version should be gtp0 (or earlier) */
2690 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2691 /* GTP 0 messages. If other version message is received we reply that we */
2692 /* only support version 0, implying that this is the only version */
2693 /* supported on this port */
2694 if (((pheader->flags & 0xe0) > 0x00)) {
2695 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002696 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2697 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002698 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2699 continue;
2700 }
2701
2702 /* Check length of gtp0 packet */
2703 if (status < GTP0_HEADER_SIZE) {
2704 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002705 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2706 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002707 continue; /* Silently discard 29.60: 11.1.2 */
2708 }
2709
2710 /* Check packet length field versus length of packet */
2711 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2712 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002713 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002714 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002715 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002716 continue; /* Silently discard */
2717 }
2718
2719 if ((gsn->mode == GTP_MODE_GGSN) &&
2720 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2721 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2722 (pheader->type == GTP_DELETE_PDP_RSP))) {
2723 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002724 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002725 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002726 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002727 continue; /* Silently discard 29.60: 11.1.4 */
2728 }
2729
2730 if ((gsn->mode == GTP_MODE_SGSN) &&
2731 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2732 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2733 (pheader->type == GTP_DELETE_PDP_REQ))) {
2734 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002735 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002736 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002737 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002738 continue; /* Silently discard 29.60: 11.1.4 */
2739 }
2740
2741 switch (pheader->type) {
2742 case GTP_ECHO_REQ:
2743 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2744 break;
2745 case GTP_ECHO_RSP:
2746 gtp_echo_conf(gsn, version, &peer, buffer, status);
2747 break;
2748 case GTP_NOT_SUPPORTED:
2749 gtp_unsup_ind(gsn, &peer, buffer, status);
2750 break;
2751 case GTP_CREATE_PDP_REQ:
2752 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2753 status);
2754 break;
2755 case GTP_CREATE_PDP_RSP:
2756 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2757 status);
2758 break;
2759 case GTP_UPDATE_PDP_REQ:
2760 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2761 status);
2762 break;
2763 case GTP_UPDATE_PDP_RSP:
2764 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2765 status);
2766 break;
2767 case GTP_DELETE_PDP_REQ:
2768 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2769 status);
2770 break;
2771 case GTP_DELETE_PDP_RSP:
2772 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2773 status);
2774 break;
2775 case GTP_ERROR:
2776 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2777 break;
2778 case GTP_GPDU:
2779 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2780 break;
2781 default:
2782 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002783 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2784 "Unknown GTP message type received: %d\n",
2785 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002786 break;
2787 }
2788 }
jjako08d331d2003-10-13 20:33:30 +00002789}
2790
jjako08d331d2003-10-13 20:33:30 +00002791int gtp_decaps1c(struct gsn_t *gsn)
2792{
Harald Weltebed35df2011-11-02 13:06:18 +01002793 unsigned char buffer[PACKET_MAX];
2794 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002795 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002796 int status;
2797 struct gtp1_header_short *pheader;
2798 int version = 1; /* TODO GTP version should be determined from header! */
2799 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002800
Harald Weltebed35df2011-11-02 13:06:18 +01002801 /* TODO: Need strategy of userspace buffering and blocking */
2802 /* Currently read is non-blocking and send is blocking. */
2803 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002804
Harald Weltebed35df2011-11-02 13:06:18 +01002805 while (1) { /* Loop until no more to read */
2806 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002807 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002808 return -1;
2809 }
2810 peerlen = sizeof(peer);
2811 if ((status =
2812 recvfrom(fd, buffer, sizeof(buffer), 0,
2813 (struct sockaddr *)&peer, &peerlen)) < 0) {
2814 if (errno == EAGAIN)
2815 return 0;
2816 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002817 LOGP(DLGTP, LOGL_ERROR,
2818 "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002819 fd, (unsigned long)buffer, sizeof(buffer),
2820 status, status ? strerror(errno) : "No error");
2821 return -1;
2822 }
jjako08d331d2003-10-13 20:33:30 +00002823
Harald Weltebed35df2011-11-02 13:06:18 +01002824 /* Need at least 1 byte in order to check version */
2825 if (status < (1)) {
2826 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002827 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2828 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002829 continue;
2830 }
jjako08d331d2003-10-13 20:33:30 +00002831
Harald Weltebed35df2011-11-02 13:06:18 +01002832 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002833
Harald Weltebed35df2011-11-02 13:06:18 +01002834 /* Version must be no larger than GTP 1 */
2835 if (((pheader->flags & 0xe0) > 0x20)) {
2836 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002837 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2838 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002839 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2840 /*29.60: 11.1.1 */
2841 continue;
2842 }
jjako08d331d2003-10-13 20:33:30 +00002843
Harald Weltebed35df2011-11-02 13:06:18 +01002844 /* Version must be at least GTP 1 */
2845 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2846 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2847 /* the message */
2848 if (((pheader->flags & 0xe0) < 0x20)) {
2849 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002850 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2851 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002852 continue;
2853 }
jjako08d331d2003-10-13 20:33:30 +00002854
Harald Weltebed35df2011-11-02 13:06:18 +01002855 /* Check packet flag field */
2856 if (((pheader->flags & 0xf7) != 0x32)) {
2857 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002858 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2859 status, "Unsupported packet flag\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002860 continue;
2861 }
jjako2c381332003-10-21 19:09:53 +00002862
Harald Weltebed35df2011-11-02 13:06:18 +01002863 /* Check length of packet */
2864 if (status < GTP1_HEADER_SIZE_LONG) {
2865 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002866 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2867 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002868 continue; /* Silently discard 29.60: 11.1.2 */
2869 }
jjako2c381332003-10-21 19:09:53 +00002870
Harald Weltebed35df2011-11-02 13:06:18 +01002871 /* Check packet length field versus length of packet */
2872 if (status !=
2873 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2874 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002875 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002876 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002877 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002878 continue; /* Silently discard */
2879 }
jjako1db1c812003-07-06 20:53:57 +00002880
Harald Weltebed35df2011-11-02 13:06:18 +01002881 /* Check for extension headers */
2882 /* TODO: We really should cycle through the headers and determine */
2883 /* if any have the comprehension required flag set */
2884 if (((pheader->flags & 0x04) != 0x00)) {
2885 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002886 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2887 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002888 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2889 status);
jjako1db1c812003-07-06 20:53:57 +00002890
Harald Weltebed35df2011-11-02 13:06:18 +01002891 continue;
2892 }
2893
2894 if ((gsn->mode == GTP_MODE_GGSN) &&
2895 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2896 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2897 (pheader->type == GTP_DELETE_PDP_RSP))) {
2898 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002899 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002900 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002901 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002902 continue; /* Silently discard 29.60: 11.1.4 */
2903 }
2904
2905 if ((gsn->mode == GTP_MODE_SGSN) &&
2906 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2907 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2908 (pheader->type == GTP_DELETE_PDP_REQ))) {
2909 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002910 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002911 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002912 "Unexpected GTP Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002913 continue; /* Silently discard 29.60: 11.1.4 */
2914 }
2915
2916 switch (pheader->type) {
2917 case GTP_ECHO_REQ:
2918 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2919 break;
2920 case GTP_ECHO_RSP:
2921 gtp_echo_conf(gsn, version, &peer, buffer, status);
2922 break;
2923 case GTP_NOT_SUPPORTED:
2924 gtp_unsup_ind(gsn, &peer, buffer, status);
2925 break;
2926 case GTP_SUPP_EXT_HEADER:
2927 gtp_extheader_ind(gsn, &peer, buffer, status);
2928 break;
2929 case GTP_CREATE_PDP_REQ:
2930 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2931 status);
2932 break;
2933 case GTP_CREATE_PDP_RSP:
2934 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2935 status);
2936 break;
2937 case GTP_UPDATE_PDP_REQ:
2938 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2939 status);
2940 break;
2941 case GTP_UPDATE_PDP_RSP:
2942 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2943 status);
2944 break;
2945 case GTP_DELETE_PDP_REQ:
2946 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2947 status);
2948 break;
2949 case GTP_DELETE_PDP_RSP:
2950 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2951 status);
2952 break;
2953 case GTP_ERROR:
2954 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2955 break;
2956 default:
2957 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002958 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2959 "Unknown GTP message type received: %u\n",
2960 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002961 break;
2962 }
2963 }
jjako52c24142002-12-16 13:33:51 +00002964}
2965
jjako08d331d2003-10-13 20:33:30 +00002966int gtp_decaps1u(struct gsn_t *gsn)
2967{
Harald Weltebed35df2011-11-02 13:06:18 +01002968 unsigned char buffer[PACKET_MAX];
2969 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002970 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002971 int status;
2972 struct gtp1_header_short *pheader;
2973 int version = 1; /* GTP version should be determined from header! */
2974 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00002975
Harald Weltebed35df2011-11-02 13:06:18 +01002976 /* TODO: Need strategy of userspace buffering and blocking */
2977 /* Currently read is non-blocking and send is blocking. */
2978 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002979
Harald Weltebed35df2011-11-02 13:06:18 +01002980 while (1) { /* Loop until no more to read */
2981 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002982 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002983 return -1;
2984 }
2985 peerlen = sizeof(peer);
2986 if ((status =
2987 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
2988 (struct sockaddr *)&peer, &peerlen)) < 0) {
2989 if (errno == EAGAIN)
2990 return 0;
2991 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002992 LOGP(DLGTP, LOGL_ERROR,
2993 "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002994 gsn->fd1u, (unsigned long)buffer,
2995 sizeof(buffer), status,
2996 status ? strerror(errno) : "No error");
2997 return -1;
2998 }
jjako08d331d2003-10-13 20:33:30 +00002999
Harald Weltebed35df2011-11-02 13:06:18 +01003000 /* Need at least 1 byte in order to check version */
3001 if (status < (1)) {
3002 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003003 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3004 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003005 continue;
3006 }
jjako08d331d2003-10-13 20:33:30 +00003007
Harald Weltebed35df2011-11-02 13:06:18 +01003008 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003009
Harald Weltebed35df2011-11-02 13:06:18 +01003010 /* Version must be no larger than GTP 1 */
3011 if (((pheader->flags & 0xe0) > 0x20)) {
3012 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003013 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3014 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003015 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3016 continue;
3017 }
jjako08d331d2003-10-13 20:33:30 +00003018
Harald Weltebed35df2011-11-02 13:06:18 +01003019 /* Version must be at least GTP 1 */
3020 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3021 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3022 /* the message */
3023 if (((pheader->flags & 0xe0) < 0x20)) {
3024 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003025 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3026 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003027 continue;
3028 }
jjako2c381332003-10-21 19:09:53 +00003029
Harald Weltebed35df2011-11-02 13:06:18 +01003030 /* Check packet flag field (allow both with and without sequence number) */
3031 if (((pheader->flags & 0xf5) != 0x30)) {
3032 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003033 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3034 status, "Unsupported packet flag\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003035 continue;
3036 }
jjako2c381332003-10-21 19:09:53 +00003037
Harald Weltebed35df2011-11-02 13:06:18 +01003038 /* Check length of packet */
3039 if (status < GTP1_HEADER_SIZE_SHORT) {
3040 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003041 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3042 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003043 continue; /* Silently discard 29.60: 11.1.2 */
3044 }
3045
3046 /* Check packet length field versus length of packet */
3047 if (status !=
3048 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3049 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003050 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003051 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003052 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003053 continue; /* Silently discard */
3054 }
3055
3056 /* Check for extension headers */
3057 /* TODO: We really should cycle through the headers and determine */
3058 /* if any have the comprehension required flag set */
3059 if (((pheader->flags & 0x04) != 0x00)) {
3060 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003061 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3062 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003063 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3064 status);
3065
3066 continue;
3067 }
3068
3069 switch (pheader->type) {
3070 case GTP_ECHO_REQ:
3071 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3072 break;
3073 case GTP_ECHO_RSP:
3074 gtp_echo_conf(gsn, version, &peer, buffer, status);
3075 break;
3076 case GTP_SUPP_EXT_HEADER:
3077 gtp_extheader_ind(gsn, &peer, buffer, status);
3078 break;
3079 case GTP_ERROR:
3080 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3081 break;
3082 /* Supported header extensions */
3083 case GTP_GPDU:
3084 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3085 break;
3086 default:
3087 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003088 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3089 "Unknown GTP message type received: %u\n",
3090 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003091 break;
3092 }
3093 }
jjako08d331d2003-10-13 20:33:30 +00003094}
3095
Harald Weltebed35df2011-11-02 13:06:18 +01003096int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003097{
Harald Weltebed35df2011-11-02 13:06:18 +01003098 union gtp_packet packet;
3099 struct sockaddr_in addr;
3100 int fd;
3101 int length;
jjako52c24142002-12-16 13:33:51 +00003102
Harald Weltebed35df2011-11-02 13:06:18 +01003103 memset(&addr, 0, sizeof(addr));
3104 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003105#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003106 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003107#endif
3108
Harald Weltebed35df2011-11-02 13:06:18 +01003109 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003110
Harald Weltebed35df2011-11-02 13:06:18 +01003111 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003112
Harald Weltebed35df2011-11-02 13:06:18 +01003113 length = GTP0_HEADER_SIZE + len;
3114 addr.sin_port = htons(GTP0_PORT);
3115 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003116
Harald Weltebed35df2011-11-02 13:06:18 +01003117 get_default_gtp(0, GTP_GPDU, &packet);
3118 packet.gtp0.h.length = hton16(len);
3119 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3120 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003121 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
jjako08d331d2003-10-13 20:33:30 +00003122
Harald Weltebed35df2011-11-02 13:06:18 +01003123 if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
3124 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003125 LOGP(DLGTP, LOGL_ERROR,
3126 "Memcpy failed: %d > %d\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003127 sizeof(union gtp_packet) -
3128 sizeof(struct gtp0_header));
3129 return EOF;
3130 }
3131 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
3132 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003133
Harald Weltebed35df2011-11-02 13:06:18 +01003134 length = GTP1_HEADER_SIZE_LONG + len;
3135 addr.sin_port = htons(GTP1U_PORT);
3136 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003137
Harald Weltebed35df2011-11-02 13:06:18 +01003138 get_default_gtp(1, GTP_GPDU, &packet);
3139 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3140 GTP1_HEADER_SIZE_LONG);
3141 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3142 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3143
3144 if (len >
3145 sizeof(union gtp_packet) -
3146 sizeof(struct gtp1_header_long)) {
3147 gsn->err_memcpy++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003148 LOGP(DLGTP, LOGL_ERROR,
3149 "Memcpy failed: %d > %d\n", len,
Harald Weltebed35df2011-11-02 13:06:18 +01003150 sizeof(union gtp_packet) -
3151 sizeof(struct gtp0_header));
3152 return EOF;
3153 }
3154 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
3155 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003156 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003157 return EOF;
3158 }
3159
3160 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003161 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003162 return -1;
3163 }
3164
3165 if (sendto(fd, &packet, length, 0,
3166 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
3167 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003168 LOGP(DLGTP, LOGL_ERROR,
3169 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003170 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3171 strerror(errno));
3172 return EOF;
3173 }
3174 return 0;
jjako52c24142002-12-16 13:33:51 +00003175}
3176
jjako52c24142002-12-16 13:33:51 +00003177/* ***********************************************************
3178 * Conversion functions
3179 *************************************************************/
3180
Harald Weltebed35df2011-11-02 13:06:18 +01003181int char2ul_t(char *src, struct ul_t dst)
3182{
3183 dst.l = strlen(src) + 1;
3184 dst.v = malloc(dst.l);
3185 dst.v[0] = dst.l - 1;
3186 memcpy(&dst.v[1], src, dst.v[0]);
3187 return 0;
jjako52c24142002-12-16 13:33:51 +00003188}
3189
3190/* ***********************************************************
3191 * IP address conversion functions
3192 * There exist several types of address representations:
3193 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3194 * Used for signalling address to mobile station. Supports IPv4
3195 * IPv6 x.25 etc. etc.
3196 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3197 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3198 * - in_addr: IPv4 address struct.
3199 * - sockaddr_in: Socket API representation of IP address and
3200 * port number.
3201 *************************************************************/
3202
Harald Weltebed35df2011-11-02 13:06:18 +01003203int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3204{
3205 eua->v[0] = 0xf1; /* IETF */
3206 eua->v[1] = 0x21; /* IPv4 */
3207 if (src) {
3208 eua->l = 6;
3209 memcpy(&eua->v[2], src, 4);
3210 } else {
3211 eua->l = 2;
3212 }
3213 return 0;
jjako52c24142002-12-16 13:33:51 +00003214}
3215
Harald Weltebed35df2011-11-02 13:06:18 +01003216int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3217{
3218 if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
3219 return -1; /* Not IPv4 address */
3220 memcpy(dst, &eua->v[2], 4);
3221 return 0;
jjako52c24142002-12-16 13:33:51 +00003222}
3223
Harald Weltebed35df2011-11-02 13:06:18 +01003224int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3225{
3226 memset(dst, 0, sizeof(struct in_addr));
3227 if (gsna->l != 4)
3228 return EOF; /* Return if not IPv4 */
3229 memcpy(dst, gsna->v, gsna->l);
3230 return 0;
jjako52c24142002-12-16 13:33:51 +00003231}
3232
Harald Weltebed35df2011-11-02 13:06:18 +01003233int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3234{
3235 memset(gsna, 0, sizeof(struct ul16_t));
3236 gsna->l = 4;
3237 memcpy(gsna->v, src, gsna->l);
3238 return 0;
jjako52c24142002-12-16 13:33:51 +00003239}