blob: 0d6d8968f233b86477b2981ec580b4d2b07c7eed [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
Harald Welte632e8432017-09-05 18:12:14 +02002 * OsmoGGSN - Gateway GPRS Support Node
jjako0fe0df02004-09-17 11:30:40 +00003 * Copyright (C) 2002, 2003, 2004 Mondru AB.
Harald Welte632e8432017-09-05 18:12:14 +02004 * Copyright (C) 2010-2011, 2016-2017 Harald Welte <laforge@gnumonks.org>
5 * Copyright (C) 2015-2017 sysmocom - s.f.m.c. GmbH
jjako52c24142002-12-16 13:33:51 +00006 *
7 * The contents of this file may be used under the terms of the GNU
8 * General Public License Version 2, provided that the above copyright
9 * notice and this permission notice is included in all copies or
10 * substantial portions of the software.
11 *
jjako52c24142002-12-16 13:33:51 +000012 */
13
14/*
15 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
16 * tunnels in the same program.
17 *
18 * TODO:
19 * - Do we need to handle fragmentation?
20 */
21
jjako52c24142002-12-16 13:33:51 +000022#ifdef __linux__
23#define _GNU_SOURCE 1
24#endif
25
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010026#include <osmocom/core/logging.h>
27#include <osmocom/core/utils.h>
28
Holger Hans Peter Freyther5816bcf2014-04-04 11:43:09 +020029#if defined(__FreeBSD__)
30#include <sys/endian.h>
31#endif
32
jjako0fe0df02004-09-17 11:30:40 +000033#include "../config.h"
34#ifdef HAVE_STDINT_H
35#include <stdint.h>
36#endif
jjako52c24142002-12-16 13:33:51 +000037
jjako52c24142002-12-16 13:33:51 +000038#include <stdio.h>
39#include <stdarg.h>
40#include <stdlib.h>
41#include <sys/time.h>
42#include <sys/types.h>
43#include <sys/socket.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46#include <sys/stat.h>
47#include <time.h>
48#include <unistd.h>
49#include <string.h>
50#include <errno.h>
51#include <fcntl.h>
Alexander Huemerdb852a12015-11-06 20:59:01 +010052#include <inttypes.h>
jjako52c24142002-12-16 13:33:51 +000053
54#include <arpa/inet.h>
55
jjakobae2cd42004-01-09 12:04:39 +000056/* #include <stdint.h> ISO C99 types */
jjako52c24142002-12-16 13:33:51 +000057
58#include "pdp.h"
59#include "gtp.h"
60#include "gtpie.h"
61#include "queue.h"
62
Harald Welte95848ba2011-11-02 18:17:50 +010063/* According to section 14.2 of 3GPP TS 29.006 version 6.9.0 */
64#define N3_REQUESTS 5
65
66#define T3_REQUEST 3
67
jjako1db1c812003-07-06 20:53:57 +000068/* Error reporting functions */
69
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +010070#define GTP_LOGPKG(pri, peer, pack, len, fmt, args...) \
71 logp2(DLGTP, pri, __FILE__, __LINE__, 0, \
72 "Packet from %s:%u, length: %d content: %s: " fmt, \
73 inet_ntoa((peer)->sin_addr), htons((peer)->sin_port), \
74 len, osmo_hexdump((const uint8_t *) pack, len), \
75 ##args);
jjako1db1c812003-07-06 20:53:57 +000076
Neels Hofmeyr9b097382015-10-12 14:00:19 +020077#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
78 LOGP(ss, level, "addr(%s:%d) " fmt, \
79 inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
80 ##args);
81
jjako52c24142002-12-16 13:33:51 +000082/* API Functions */
83
Harald Weltebed35df2011-11-02 13:06:18 +010084const char *gtp_version()
jjako52c24142002-12-16 13:33:51 +000085{
Harald Weltebed35df2011-11-02 13:06:18 +010086 return VERSION;
jjako52c24142002-12-16 13:33:51 +000087}
88
Maxe6612772018-01-11 18:25:37 +010089const struct value_string gtp_type_names[] = {
90 { GTP_ECHO_REQ, "Echo Request" },
91 { GTP_ECHO_RSP, "Echo Response" },
92 { GTP_NOT_SUPPORTED, "Version Not Supported" },
93 { GTP_ALIVE_REQ, "Node Alive Request" },
94 { GTP_ALIVE_RSP, "Node Alive Response" },
95 { GTP_REDIR_REQ, "Redirection Request" },
96 { GTP_REDIR_RSP, "Redirection Response" },
97 { GTP_CREATE_PDP_REQ, "Create PDP Context Request" },
98 { GTP_CREATE_PDP_RSP, "Create PDP Context Response" },
99 { GTP_UPDATE_PDP_REQ, "Update PDP Context Request" },
100 { GTP_UPDATE_PDP_RSP, "Update PDP Context Response" },
101 { GTP_DELETE_PDP_REQ, "Delete PDP Context Request" },
102 { GTP_DELETE_PDP_RSP, "Delete PDP Context Response" },
103 { GTP_ERROR, "Error Indication" },
104 { GTP_PDU_NOT_REQ, "PDU Notification Request" },
105 { GTP_PDU_NOT_RSP, "PDU Notification Response" },
106 { GTP_PDU_NOT_REJ_REQ, "PDU Notification Reject Request" },
107 { GTP_PDU_NOT_REJ_RSP, "PDU Notification Reject Response" },
108 { GTP_SUPP_EXT_HEADER, "Supported Extension Headers Notification" },
109 { GTP_SND_ROUTE_REQ, "Send Routeing Information for GPRS Request" },
110 { GTP_SND_ROUTE_RSP, "Send Routeing Information for GPRS Response" },
111 { GTP_FAILURE_REQ, "Failure Report Request" },
112 { GTP_FAILURE_RSP, "Failure Report Response" },
113 { GTP_MS_PRESENT_REQ, "Note MS GPRS Present Request" },
114 { GTP_MS_PRESENT_RSP, "Note MS GPRS Present Response" },
115 { GTP_IDEN_REQ, "Identification Request" },
116 { GTP_IDEN_RSP, "Identification Response" },
117 { GTP_SGSN_CONTEXT_REQ,"SGSN Context Request" },
118 { GTP_SGSN_CONTEXT_RSP,"SGSN Context Response" },
119 { GTP_SGSN_CONTEXT_ACK,"SGSN Context Acknowledge" },
120 { GTP_FWD_RELOC_REQ, "Forward Relocation Request" },
121 { GTP_FWD_RELOC_RSP, "Forward Relocation Response" },
122 { GTP_FWD_RELOC_COMPL, "Forward Relocation Complete" },
123 { GTP_RELOC_CANCEL_REQ,"Relocation Cancel Request" },
124 { GTP_RELOC_CANCEL_RSP,"Relocation Cancel Response" },
125 { GTP_FWD_SRNS, "Forward SRNS Context" },
126 { GTP_FWD_RELOC_ACK, "Forward Relocation Complete Acknowledge" },
127 { GTP_FWD_SRNS_ACK, "Forward SRNS Context Acknowledge" },
128 { GTP_DATA_TRAN_REQ, "Data Record Transfer Request" },
129 { GTP_DATA_TRAN_RSP, "Data Record Transfer Response" },
130 { GTP_GPDU, "G-PDU" },
131 { 0, NULL }
132};
133
jjako52c24142002-12-16 13:33:51 +0000134/* gtp_new */
135/* gtp_free */
136
Harald Weltebed35df2011-11-02 13:06:18 +0100137int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
138 uint64_t imsi, uint8_t nsapi)
139{
Harald Weltee257be12017-08-12 14:55:09 +0200140 int rc;
141 rc = pdp_newpdp(pdp, imsi, nsapi, NULL);
142 if (!rc && *pdp)
143 (*pdp)->gsn = gsn;
144 return rc;
jjako52c24142002-12-16 13:33:51 +0000145}
146
Harald Weltebed35df2011-11-02 13:06:18 +0100147int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
148{
149 return pdp_freepdp(pdp);
jjako52c24142002-12-16 13:33:51 +0000150}
151
jjako52c24142002-12-16 13:33:51 +0000152/* gtp_gpdu */
153
Harald Weltebed35df2011-11-02 13:06:18 +0100154extern int gtp_fd(struct gsn_t *gsn)
155{
156 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000157}
158
159/* gtp_decaps */
160/* gtp_retrans */
161/* gtp_retranstimeout */
162
jjako08d331d2003-10-13 20:33:30 +0000163int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100164 int (*cb) (struct sockaddr_in * peer))
165{
166 gsn->cb_unsup_ind = cb;
167 return 0;
jjako08d331d2003-10-13 20:33:30 +0000168}
169
jjako2c381332003-10-21 19:09:53 +0000170int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100171 int (*cb) (struct sockaddr_in * peer))
172{
173 gsn->cb_extheader_ind = cb;
174 return 0;
jjako2c381332003-10-21 19:09:53 +0000175}
176
jjako08d331d2003-10-13 20:33:30 +0000177/* API: Initialise delete context callback */
178/* Called whenever a pdp context is deleted for any reason */
Harald Weltebed35df2011-11-02 13:06:18 +0100179int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
jjako52c24142002-12-16 13:33:51 +0000180{
Harald Weltebed35df2011-11-02 13:06:18 +0100181 gsn->cb_delete_context = cb;
182 return 0;
jjako52c24142002-12-16 13:33:51 +0000183}
184
jjako52c24142002-12-16 13:33:51 +0000185int gtp_set_cb_conf(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100186 int (*cb) (int type, int cause,
187 struct pdp_t * pdp, void *cbp))
188{
189 gsn->cb_conf = cb;
190 return 0;
jjako52c24142002-12-16 13:33:51 +0000191}
192
Harald Welte629e9862010-12-24 20:58:09 +0100193int gtp_set_cb_recovery(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100194 int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
195{
196 gsn->cb_recovery = cb;
197 return 0;
Harald Welte629e9862010-12-24 20:58:09 +0100198}
199
jjako08d331d2003-10-13 20:33:30 +0000200extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +0100201 int (*cb_data_ind) (struct pdp_t * pdp,
202 void *pack, unsigned len))
jjako52c24142002-12-16 13:33:51 +0000203{
Harald Weltebed35df2011-11-02 13:06:18 +0100204 gsn->cb_data_ind = cb_data_ind;
205 return 0;
jjako52c24142002-12-16 13:33:51 +0000206}
207
jjako08d331d2003-10-13 20:33:30 +0000208/**
209 * get_default_gtp()
210 * Generate a GPRS Tunneling Protocol signalling packet header, depending
211 * on GTP version and message type. pdp is used for teid/flow label.
212 * *packet must be allocated by the calling function, and be large enough
213 * to hold the packet header.
214 * returns the length of the header. 0 on error.
215 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100216static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
217{
218 struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
219 struct gtp1_header_long *gtp1_default =
220 (struct gtp1_header_long *)packet;
221 switch (version) {
222 case 0:
223 /* Initialise "standard" GTP0 header */
224 memset(gtp0_default, 0, sizeof(struct gtp0_header));
225 gtp0_default->flags = 0x1e;
226 gtp0_default->type = hton8(type);
227 gtp0_default->spare1 = 0xff;
228 gtp0_default->spare2 = 0xff;
229 gtp0_default->spare3 = 0xff;
230 gtp0_default->number = 0xff;
231 return GTP0_HEADER_SIZE;
232 case 1:
233 /* Initialise "standard" GTP1 header */
234 /* 29.060: 8.2: S=1 and PN=0 */
235 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
236 /* and Supported Extension Headers Notification, the S field shall be */
237 /* set to 1 */
238 /* Currently extension headers are not supported */
239 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
Harald Weltefed598f2017-09-24 16:39:22 +0800240 /* No extension, enable sequence, no N-PDU */
241 gtp1_default->flags = GTPHDR_F_VER(1) | GTP1HDR_F_GTP1 | GTP1HDR_F_SEQ;
Harald Weltebed35df2011-11-02 13:06:18 +0100242 gtp1_default->type = hton8(type);
243 return GTP1_HEADER_SIZE_LONG;
244 default:
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100245 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100246 "Unknown GTP packet version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +0100247 return 0;
248 }
jjako52c24142002-12-16 13:33:51 +0000249}
250
jjako08d331d2003-10-13 20:33:30 +0000251/**
252 * get_seq()
253 * Get sequence number of a packet.
254 * Returns 0 on error
255 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100256static uint16_t get_seq(void *pack)
257{
258 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800259 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000260
Harald Weltefed598f2017-09-24 16:39:22 +0800261 if (ver == 0) {
Harald Weltebed35df2011-11-02 13:06:18 +0100262 return ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800263 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100264 return ntoh16(packet->gtp1l.h.seq);
265 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100266 return 0;
267 }
jjako08d331d2003-10-13 20:33:30 +0000268}
269
270/**
271 * get_tid()
272 * Get tunnel identifier of a packet.
273 * Returns 0 on error
274 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100275static uint64_t get_tid(void *pack)
276{
277 union gtp_packet *packet = (union gtp_packet *)pack;
278
Harald Weltefed598f2017-09-24 16:39:22 +0800279 if (GTPHDR_F_GET_VER(packet->flags) == 0) { /* Version 0 */
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100280 return be64toh(packet->gtp0.h.tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100281 }
282 return 0;
jjako08d331d2003-10-13 20:33:30 +0000283}
284
285/**
286 * get_hlen()
287 * Get the header length of a packet.
288 * Returns 0 on error
289 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100290static uint16_t get_hlen(void *pack)
291{
292 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800293 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000294
Harald Weltefed598f2017-09-24 16:39:22 +0800295 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100296 return GTP0_HEADER_SIZE;
Harald Weltefed598f2017-09-24 16:39:22 +0800297 } else if (ver == 1 && (packet->flags & 0x07) == 0) { /* Short version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100298 return GTP1_HEADER_SIZE_SHORT;
Harald Weltefed598f2017-09-24 16:39:22 +0800299 } else if (ver == 1) { /* Version 1 with seq/n-pdu/ext */
300 return GTP1_HEADER_SIZE_LONG;
Harald Weltebed35df2011-11-02 13:06:18 +0100301 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100302 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100303 return 0;
304 }
jjako08d331d2003-10-13 20:33:30 +0000305}
306
307/**
308 * get_tei()
309 * Get the tunnel endpoint identifier (flow label) of a packet.
310 * Returns 0xffffffff on error.
311 **/
Harald Weltebed35df2011-11-02 13:06:18 +0100312static uint32_t get_tei(void *pack)
313{
314 union gtp_packet *packet = (union gtp_packet *)pack;
Harald Weltefed598f2017-09-24 16:39:22 +0800315 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
jjako08d331d2003-10-13 20:33:30 +0000316
Harald Weltefed598f2017-09-24 16:39:22 +0800317 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100318 return ntoh16(packet->gtp0.h.flow);
Harald Weltefed598f2017-09-24 16:39:22 +0800319 } else if (ver == 1) { /* Version 1 */
Harald Weltebed35df2011-11-02 13:06:18 +0100320 return ntoh32(packet->gtp1l.h.tei);
321 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100322 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100323 return 0xffffffff;
324 }
jjako08d331d2003-10-13 20:33:30 +0000325}
jjakoa7cd2492003-04-11 09:40:12 +0000326
jjako52c24142002-12-16 13:33:51 +0000327/* ***********************************************************
328 * Reliable delivery of signalling messages
329 *
330 * Sequence numbers are used for both signalling messages and
331 * data messages.
332 *
333 * For data messages each tunnel maintains a sequence counter,
334 * which is incremented by one each time a new data message
335 * is sent. The sequence number starts at (0) zero at tunnel
336 * establishment, and wraps around at 65535 (29.060 9.3.1.1
337 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
338 * or can be used to check the validity of the message in the
339 * receiver, or for reordering af packets.
340 *
341 * For signalling messages the sequence number is used by
342 * signalling messages for which a response is defined. A response
343 * message should copy the sequence from the corresponding request
344 * message. The sequence number "unambiguously" identifies a request
345 * message within a given path, with a path being defined as a set of
346 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
347 * messages shall be responded to, and all response messages associated
348 * with a certain request shall always include the same information"
349 *
350 * We take this to mean that the GSN transmitting a request is free to
351 * choose the sequence number, as long as it is unique within a given path.
352 * It means that we are allowed to count backwards, or roll over at 17
353 * if we prefer that. It also means that we can use the same counter for
354 * all paths. This has the advantage that the transmitted request sequence
355 * numbers are unique within each GSN, and also we dont have to mess around
356 * with path setup and teardown.
357 *
358 * If a response message is lost, the request will be retransmitted, and
359 * the receiving GSN will receive a "duplicated" request. The standard
360 * requires the receiving GSN to send a response, with the same information
361 * as in the original response. For most messages this happens automatically:
362 *
363 * Echo: Automatically dublicates the original response
364 * Create pdp context: The SGSN may send create context request even if
365 * a context allready exist (imsi+nsapi?). This means that the reply will
366 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000367 * side effects in the application which is asked twice to validate
368 * the login.
jjako52c24142002-12-16 13:33:51 +0000369 * Update pdp context: Automatically dublicates the original response???
370 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
371 * a nonexist reply message.
372 *
373 * The correct solution will be to make a queue containing response messages.
374 * This queue should be checked whenever a request is received. If the
375 * response is allready in the queue that response should be transmitted.
376 * It should be possible to find messages in this queue on the basis of
377 * the sequence number and peer GSN IP address (The sequense number is unique
378 * within each path). This need to be implemented by a hash table. Furthermore
379 * it should be possibly to delete messages based on a timeout. This can be
380 * achieved by means of a linked list. The timeout value need to be larger
381 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
382 * set in the peer GSN, so there is no way to know these parameters. On the
383 * other hand the timeout value need to be so small that we do not receive
384 * wraparound sequence numbere before the message is deleted. 60 seconds is
385 * probably not a bad choise.
386 *
387 * This queue however is first really needed from gtp1.
388 *
389 * gtp_req:
390 * Send off a signalling message with appropiate sequence
391 * number. Store packet in queue.
392 * gtp_conf:
393 * Remove an incoming confirmation from the queue
394 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000395 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000396 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000397 * gtp_notification:
398 * Send off a notification message. This is neither a request nor
399 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000400 * gtp_retrans:
401 * Retransmit any outstanding packets which have exceeded
402 * a predefined timeout.
403 *************************************************************/
404
jjako08d331d2003-10-13 20:33:30 +0000405int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
Harald Weltebed35df2011-11-02 13:06:18 +0100406 union gtp_packet *packet, int len,
407 struct in_addr *inetaddr, void *cbp)
408{
Harald Weltefed598f2017-09-24 16:39:22 +0800409 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100410 struct sockaddr_in addr;
411 struct qmsg_t *qmsg;
412 int fd;
jjako08d331d2003-10-13 20:33:30 +0000413
Harald Weltebed35df2011-11-02 13:06:18 +0100414 memset(&addr, 0, sizeof(addr));
415 addr.sin_family = AF_INET;
416 addr.sin_addr = *inetaddr;
jjako0fe0df02004-09-17 11:30:40 +0000417#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100418 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000419#endif
jjako52c24142002-12-16 13:33:51 +0000420
Harald Weltefed598f2017-09-24 16:39:22 +0800421 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100422 addr.sin_port = htons(GTP0_PORT);
423 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
424 packet->gtp0.h.seq = hton16(gsn->seq_next);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100425 if (pdp) {
Harald Weltebed35df2011-11-02 13:06:18 +0100426 packet->gtp0.h.tid =
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +0100427 htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100428 }
Harald Weltebed35df2011-11-02 13:06:18 +0100429 if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
430 || (packet->gtp0.h.type == GTP_ERROR)))
431 packet->gtp0.h.flow = hton16(pdp->flru);
432 else if (pdp)
433 packet->gtp0.h.flow = hton16(pdp->flrc);
434 fd = gsn->fd0;
Harald Weltefed598f2017-09-24 16:39:22 +0800435 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100436 addr.sin_port = htons(GTP1C_PORT);
437 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
438 packet->gtp1l.h.seq = hton16(gsn->seq_next);
439 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
440 (packet->gtp1l.h.type == GTP_ERROR)))
441 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
442 else if (pdp)
443 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
444 fd = gsn->fd1c;
445 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100446 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100447 return -1;
448 }
jjako52c24142002-12-16 13:33:51 +0000449
Harald Weltebed35df2011-11-02 13:06:18 +0100450 if (sendto(fd, packet, len, 0,
451 (struct sockaddr *)&addr, sizeof(addr)) < 0) {
452 gsn->err_sendto++;
Max14b1b632017-08-21 20:14:59 +0200453 LOGP(DLGTP, LOGL_ERROR, "Sendto(fd=%d, msg=%lx, len=%d, dst=%s) failed: Error = %s\n", fd,
454 (unsigned long)&packet, len, inet_ntoa(addr.sin_addr), strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100455 return -1;
456 }
457
458 /* Use new queue structure */
459 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
460 gsn->err_queuefull++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100461 LOGP(DLGTP, LOGL_ERROR,
462 "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100463 } else {
464 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
465 qmsg->l = len;
Harald Welte95848ba2011-11-02 18:17:50 +0100466 qmsg->timeout = time(NULL) + T3_REQUEST; /* When to timeout */
Harald Weltebed35df2011-11-02 13:06:18 +0100467 qmsg->retrans = 0; /* No retransmissions so far */
468 qmsg->cbp = cbp;
469 qmsg->type = ntoh8(packet->gtp0.h.type);
470 qmsg->fd = fd;
471 }
472 gsn->seq_next++; /* Count up this time */
473 return 0;
jjako52c24142002-12-16 13:33:51 +0000474}
475
476/* gtp_conf
477 * Remove signalling packet from retransmission queue.
478 * return 0 on success, EOF if packet was not found */
479
480int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100481 union gtp_packet *packet, int len, uint8_t * type, void **cbp)
482{
Harald Weltefed598f2017-09-24 16:39:22 +0800483 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100484 uint16_t seq;
jjako08d331d2003-10-13 20:33:30 +0000485
Harald Weltefed598f2017-09-24 16:39:22 +0800486 if (ver == 0)
Harald Weltebed35df2011-11-02 13:06:18 +0100487 seq = ntoh16(packet->gtp0.h.seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800488 else if (ver == 1 && (packet->gtp1l.h.flags & GTP1HDR_F_SEQ))
Harald Weltebed35df2011-11-02 13:06:18 +0100489 seq = ntoh16(packet->gtp1l.h.seq);
490 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100491 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
492 "Unknown GTP packet version\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100493 return EOF;
494 }
jjako08d331d2003-10-13 20:33:30 +0000495
Harald Weltebed35df2011-11-02 13:06:18 +0100496 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
497 gsn->err_seq++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100498 GTP_LOGPKG(LOGL_ERROR, peer, packet, len,
499 "Confirmation packet not found in queue\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100500 return EOF;
501 }
jjako52c24142002-12-16 13:33:51 +0000502
Harald Weltebed35df2011-11-02 13:06:18 +0100503 return 0;
jjako52c24142002-12-16 13:33:51 +0000504}
505
Harald Weltebed35df2011-11-02 13:06:18 +0100506int gtp_retrans(struct gsn_t *gsn)
507{
508 /* Retransmit any outstanding packets */
509 /* Remove from queue if maxretrans exceeded */
510 time_t now;
511 struct qmsg_t *qmsg;
512 now = time(NULL);
513 /*printf("Retrans: New beginning %d\n", (int) now); */
jjako52c24142002-12-16 13:33:51 +0000514
Harald Welte95848ba2011-11-02 18:17:50 +0100515 /* get first element in queue, as long as the timeout of that
516 * element has expired */
Harald Weltebed35df2011-11-02 13:06:18 +0100517 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
518 (qmsg->timeout <= now)) {
519 /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
Harald Welte95848ba2011-11-02 18:17:50 +0100520 if (qmsg->retrans > N3_REQUESTS) { /* To many retrans */
Harald Weltebed35df2011-11-02 13:06:18 +0100521 if (gsn->cb_conf)
522 gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
523 queue_freemsg(gsn->queue_req, qmsg);
524 } else {
525 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
526 (struct sockaddr *)&qmsg->peer,
527 sizeof(struct sockaddr_in)) < 0) {
528 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100529 LOGP(DLGTP, LOGL_ERROR,
530 "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100531 gsn->fd0, (unsigned long)&qmsg->p,
532 qmsg->l, strerror(errno));
533 }
534 queue_back(gsn->queue_req, qmsg);
Harald Welte95848ba2011-11-02 18:17:50 +0100535 qmsg->timeout = now + T3_REQUEST;
Harald Weltebed35df2011-11-02 13:06:18 +0100536 qmsg->retrans++;
537 }
538 }
jjako52c24142002-12-16 13:33:51 +0000539
Harald Weltebed35df2011-11-02 13:06:18 +0100540 /* Also clean up reply timeouts */
541 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
542 (qmsg->timeout < now)) {
543 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
544 queue_freemsg(gsn->queue_resp, qmsg);
545 }
jjako52c24142002-12-16 13:33:51 +0000546
Harald Weltebed35df2011-11-02 13:06:18 +0100547 return 0;
jjako52c24142002-12-16 13:33:51 +0000548}
549
Harald Weltebed35df2011-11-02 13:06:18 +0100550int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
551{
552 time_t now, later;
553 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000554
Harald Weltebed35df2011-11-02 13:06:18 +0100555 if (queue_getfirst(gsn->queue_req, &qmsg)) {
556 timeout->tv_sec = 10;
557 timeout->tv_usec = 0;
558 } else {
559 now = time(NULL);
560 later = qmsg->timeout;
561 timeout->tv_sec = later - now;
562 timeout->tv_usec = 0;
563 if (timeout->tv_sec < 0)
564 timeout->tv_sec = 0; /* No negative allowed */
565 if (timeout->tv_sec > 10)
566 timeout->tv_sec = 10; /* Max sleep for 10 sec */
567 }
568 return 0;
jjako52c24142002-12-16 13:33:51 +0000569}
570
Harald Weltebed35df2011-11-02 13:06:18 +0100571int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
jjako08d331d2003-10-13 20:33:30 +0000572 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100573 struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
574{
Harald Weltefed598f2017-09-24 16:39:22 +0800575 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100576 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000577
Harald Weltefed598f2017-09-24 16:39:22 +0800578 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100579 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
580 packet->gtp0.h.seq = hton16(seq);
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +0100581 packet->gtp0.h.tid = htobe64(tid);
Harald Weltebed35df2011-11-02 13:06:18 +0100582 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
583 (packet->gtp0.h.type == GTP_ERROR)))
584 packet->gtp0.h.flow = hton16(pdp->flru);
585 else if (pdp)
586 packet->gtp0.h.flow = hton16(pdp->flrc);
Harald Weltefed598f2017-09-24 16:39:22 +0800587 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100588 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
589 packet->gtp1l.h.seq = hton16(seq);
590 if (pdp && (fd == gsn->fd1u))
591 packet->gtp1l.h.tei = hton32(pdp->teid_gn);
592 else if (pdp)
593 packet->gtp1l.h.tei = hton32(pdp->teic_gn);
594 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100595 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100596 return -1;
597 }
jjako08d331d2003-10-13 20:33:30 +0000598
Harald Weltebed35df2011-11-02 13:06:18 +0100599 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100600 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100601 return -1;
602 }
jjako52c24142002-12-16 13:33:51 +0000603
Harald Weltebed35df2011-11-02 13:06:18 +0100604 if (sendto(fd, packet, len, 0,
605 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
606 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100607 LOGP(DLGTP, LOGL_ERROR,
608 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100609 (unsigned long)&packet, len, strerror(errno));
610 return -1;
611 }
612
613 /* Use new queue structure */
614 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
615 gsn->err_queuefull++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100616 LOGP(DLGTP, LOGL_ERROR, "Retransmit queue is full\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100617 } else {
618 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
619 qmsg->l = len;
620 qmsg->timeout = time(NULL) + 60; /* When to timeout */
621 qmsg->retrans = 0; /* No retransmissions so far */
622 qmsg->cbp = NULL;
623 qmsg->type = 0;
624 qmsg->fd = fd;
625 }
626 return 0;
jjako52c24142002-12-16 13:33:51 +0000627}
628
jjako2c381332003-10-21 19:09:53 +0000629int gtp_notification(struct gsn_t *gsn, int version,
630 union gtp_packet *packet, int len,
Harald Weltebed35df2011-11-02 13:06:18 +0100631 struct sockaddr_in *peer, int fd, uint16_t seq)
632{
jjako2c381332003-10-21 19:09:53 +0000633
Harald Weltefed598f2017-09-24 16:39:22 +0800634 uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100635 struct sockaddr_in addr;
jjako2c381332003-10-21 19:09:53 +0000636
Harald Weltebed35df2011-11-02 13:06:18 +0100637 memcpy(&addr, peer, sizeof(addr));
jjako2c381332003-10-21 19:09:53 +0000638
Harald Weltebed35df2011-11-02 13:06:18 +0100639 /* In GTP0 notifications are treated as replies. In GTP1 they
640 are requests for which there is no reply */
jjako2c381332003-10-21 19:09:53 +0000641
Harald Weltebed35df2011-11-02 13:06:18 +0100642 if (fd == gsn->fd1c)
643 addr.sin_port = htons(GTP1C_PORT);
644 else if (fd == gsn->fd1u)
645 addr.sin_port = htons(GTP1C_PORT);
jjako2c381332003-10-21 19:09:53 +0000646
Harald Weltefed598f2017-09-24 16:39:22 +0800647 if (ver == 0) { /* Version 0 */
Harald Weltebed35df2011-11-02 13:06:18 +0100648 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
649 packet->gtp0.h.seq = hton16(seq);
Harald Weltefed598f2017-09-24 16:39:22 +0800650 } else if (ver == 1 && (packet->flags & GTP1HDR_F_SEQ)) { /* Version 1 with seq */
Harald Weltebed35df2011-11-02 13:06:18 +0100651 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
652 packet->gtp1l.h.seq = hton16(seq);
653 } else {
Harald Welted37b80a2016-12-15 18:33:15 +0100654 LOGP(DLGTP, LOGL_ERROR, "Unknown packet flags: 0x%02x\n", packet->flags);
Harald Weltebed35df2011-11-02 13:06:18 +0100655 return -1;
656 }
657
658 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100659 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100660 return -1;
661 }
662
663 if (sendto(fd, packet, len, 0,
664 (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
665 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100666 LOGP(DLGTP, LOGL_ERROR,
667 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +0100668 (unsigned long)&packet, len, strerror(errno));
669 return -1;
670 }
671 return 0;
jjako2c381332003-10-21 19:09:53 +0000672}
673
Harald Weltebed35df2011-11-02 13:06:18 +0100674int gtp_dublicate(struct gsn_t *gsn, int version,
675 struct sockaddr_in *peer, uint16_t seq)
676{
677 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000678
Harald Weltebed35df2011-11-02 13:06:18 +0100679 if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
680 return EOF; /* Notfound */
681 }
jjakoa7cd2492003-04-11 09:40:12 +0000682
Harald Weltebed35df2011-11-02 13:06:18 +0100683 if (fcntl(qmsg->fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100684 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100685 return -1;
686 }
687
688 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
689 (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
690 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100691 LOGP(DLGTP, LOGL_ERROR,
692 "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100693 qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
694 strerror(errno));
695 }
696 return 0;
jjako52c24142002-12-16 13:33:51 +0000697}
698
jjako52c24142002-12-16 13:33:51 +0000699/* Perform restoration and recovery error handling as described in 29.060 */
Harald Weltebed35df2011-11-02 13:06:18 +0100700static void log_restart(struct gsn_t *gsn)
701{
jjako52c24142002-12-16 13:33:51 +0000702 FILE *f;
Emmanuel Bretelle111e0542010-09-06 19:49:16 +0200703 int i, rc;
jjako52c24142002-12-16 13:33:51 +0000704 int counter = 0;
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200705 char *filename;
jjako52c24142002-12-16 13:33:51 +0000706
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200707 filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
708 OSMO_ASSERT(filename);
jjako52c24142002-12-16 13:33:51 +0000709
710 /* We try to open file. On failure we will later try to create file */
711 if (!(f = fopen(filename, "r"))) {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +0100712 LOGP(DLGTP, LOGL_NOTICE,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100713 "State information file (%s) not found. Creating new file.\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100714 filename);
715 } else {
Harald Weltebed35df2011-11-02 13:06:18 +0100716 rc = fscanf(f, "%d", &counter);
717 if (rc != 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100718 LOGP(DLGTP, LOGL_ERROR,
719 "fscanf failed to read counter value\n");
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100720 goto close_file;
Harald Weltebed35df2011-11-02 13:06:18 +0100721 }
722 if (fclose(f)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100723 LOGP(DLGTP, LOGL_ERROR,
724 "fclose failed: Error = %s\n", strerror(errno));
Harald Weltebed35df2011-11-02 13:06:18 +0100725 }
jjako52c24142002-12-16 13:33:51 +0000726 }
Harald Weltebed35df2011-11-02 13:06:18 +0100727
728 gsn->restart_counter = (unsigned char)counter;
jjako52c24142002-12-16 13:33:51 +0000729 gsn->restart_counter++;
Harald Weltebed35df2011-11-02 13:06:18 +0100730
Neels Hofmeyrf41f5862016-09-19 03:35:53 +0200731 /* Keep the umask closely wrapped around our fopen() call in case the
732 * log outputs cause file creation. */
733 i = umask(022);
734 f = fopen(filename, "w");
735 umask(i);
736 if (!f) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100737 LOGP(DLGTP, LOGL_ERROR,
738 "fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
Harald Weltebed35df2011-11-02 13:06:18 +0100739 "w", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200740 goto free_filename;
jjako52c24142002-12-16 13:33:51 +0000741 }
742
jjako52c24142002-12-16 13:33:51 +0000743 fprintf(f, "%d\n", gsn->restart_counter);
Holger Hans Peter Freyther8ddb6802016-01-23 10:40:52 +0100744close_file:
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200745 if (fclose(f))
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100746 LOGP(DLGTP, LOGL_ERROR,
747 "fclose failed: Error = %s\n", strerror(errno));
Neels Hofmeyrf7611c32016-08-18 03:53:09 +0200748free_filename:
749 talloc_free(filename);
jjako52c24142002-12-16 13:33:51 +0000750}
751
jjako1db1c812003-07-06 20:53:57 +0000752int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
Harald Weltebed35df2011-11-02 13:06:18 +0100753 int mode)
jjako52c24142002-12-16 13:33:51 +0000754{
Harald Weltebed35df2011-11-02 13:06:18 +0100755 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000756
Max14b1b632017-08-21 20:14:59 +0200757 LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
jjako52c24142002-12-16 13:33:51 +0000758
Harald Weltebed35df2011-11-02 13:06:18 +0100759 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
jjakoa7cd2492003-04-11 09:40:12 +0000760
Harald Weltebed35df2011-11-02 13:06:18 +0100761 (*gsn)->statedir = statedir;
762 log_restart(*gsn);
jjako52c24142002-12-16 13:33:51 +0000763
Harald Weltebed35df2011-11-02 13:06:18 +0100764 /* Initialise sequence number */
765 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000766
Harald Weltebed35df2011-11-02 13:06:18 +0100767 /* Initialise request retransmit queue */
768 queue_new(&(*gsn)->queue_req);
769 queue_new(&(*gsn)->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000770
Harald Weltebed35df2011-11-02 13:06:18 +0100771 /* Initialise pdp table */
772 pdp_init();
jjako08d331d2003-10-13 20:33:30 +0000773
Harald Weltebed35df2011-11-02 13:06:18 +0100774 /* Initialise call back functions */
775 (*gsn)->cb_create_context_ind = 0;
776 (*gsn)->cb_delete_context = 0;
777 (*gsn)->cb_unsup_ind = 0;
778 (*gsn)->cb_conf = 0;
779 (*gsn)->cb_data_ind = 0;
780
781 /* Store function parameters */
782 (*gsn)->gsnc = *listen;
783 (*gsn)->gsnu = *listen;
784 (*gsn)->mode = mode;
785
786 /* Create GTP version 0 socket */
787 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
788 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100789 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200790 "GTPv0 socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100791 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200792 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100793 }
794
795 memset(&addr, 0, sizeof(addr));
796 addr.sin_family = AF_INET;
797 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
798 addr.sin_port = htons(GTP0_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000799#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100800 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000801#endif
jjako08d331d2003-10-13 20:33:30 +0000802
Harald Weltebed35df2011-11-02 13:06:18 +0100803 if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
804 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200805 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
806 "bind(fd0=%d) failed: Error = %s\n",
807 (*gsn)->fd0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200808 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100809 }
jjako08d331d2003-10-13 20:33:30 +0000810
Harald Weltebed35df2011-11-02 13:06:18 +0100811 /* Create GTP version 1 control plane socket */
812 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
813 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100814 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200815 "GTPv1 control plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100816 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200817 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100818 }
819
820 memset(&addr, 0, sizeof(addr));
821 addr.sin_family = AF_INET;
822 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
823 addr.sin_port = htons(GTP1C_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000824#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100825 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000826#endif
jjako08d331d2003-10-13 20:33:30 +0000827
Harald Weltebed35df2011-11-02 13:06:18 +0100828 if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
829 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200830 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
831 "bind(fd1c=%d) failed: Error = %s\n",
832 (*gsn)->fd1c, strerror(errno));
Max28318872017-05-16 17:03:02 +0200833 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100834 }
jjako08d331d2003-10-13 20:33:30 +0000835
Harald Weltebed35df2011-11-02 13:06:18 +0100836 /* Create GTP version 1 user plane socket */
837 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
838 (*gsn)->err_socket++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100839 LOGP(DLGTP, LOGL_ERROR,
Max28318872017-05-16 17:03:02 +0200840 "GTPv1 user plane socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +0100841 AF_INET, SOCK_DGRAM, 0, strerror(errno));
Max28318872017-05-16 17:03:02 +0200842 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100843 }
844
845 memset(&addr, 0, sizeof(addr));
846 addr.sin_family = AF_INET;
847 addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
848 addr.sin_port = htons(GTP1U_PORT);
jjako0fe0df02004-09-17 11:30:40 +0000849#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +0100850 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +0000851#endif
jjako52c24142002-12-16 13:33:51 +0000852
Harald Weltebed35df2011-11-02 13:06:18 +0100853 if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
854 (*gsn)->err_socket++;
Neels Hofmeyr9b097382015-10-12 14:00:19 +0200855 LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
Neels Hofmeyre845cb92015-10-12 14:00:22 +0200856 "bind(fd1u=%d) failed: Error = %s\n",
857 (*gsn)->fd1u, strerror(errno));
Max28318872017-05-16 17:03:02 +0200858 return -errno;
Harald Weltebed35df2011-11-02 13:06:18 +0100859 }
860
861 return 0;
jjako52c24142002-12-16 13:33:51 +0000862}
863
Harald Weltebed35df2011-11-02 13:06:18 +0100864int gtp_free(struct gsn_t *gsn)
865{
jjako52c24142002-12-16 13:33:51 +0000866
Harald Weltebed35df2011-11-02 13:06:18 +0100867 /* Clean up retransmit queues */
868 queue_free(gsn->queue_req);
869 queue_free(gsn->queue_resp);
jjako52c24142002-12-16 13:33:51 +0000870
Harald Weltebed35df2011-11-02 13:06:18 +0100871 close(gsn->fd0);
872 close(gsn->fd1c);
873 close(gsn->fd1u);
874
875 free(gsn);
876 return 0;
jjako52c24142002-12-16 13:33:51 +0000877}
878
879/* ***********************************************************
880 * Path management messages
881 * Messages: echo and version not supported.
882 * A path is connection between two UDP/IP endpoints
883 *
884 * A path is either using GTP0 or GTP1. A path can be
885 * established by any kind of GTP message??
886
887 * Which source port to use?
888 * GTP-C request destination port is 2123/3386
889 * GTP-U request destination port is 2152/3386
890 * T-PDU destination port is 2152/3386.
891 * For the above messages the source port is locally allocated.
892 * For response messages src=rx-dst and dst=rx-src.
893 * For simplicity we should probably use 2123+2152/3386 as
894 * src port even for the cases where src can be locally
895 * allocated. This also means that we have to listen only to
896 * the same ports.
897 * For response messages we need to be able to respond to
898 * the relevant src port even if it is locally allocated by
899 * the peer.
900 *
901 * The need for path management!
902 * We might need to keep a list of active paths. This might
903 * be in the form of remote IP address + UDP port numbers.
904 * (We will consider a path astablished if we have a context
905 * with the node in question)
906 *************************************************************/
907
908/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000909int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
910 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000911{
Harald Weltebed35df2011-11-02 13:06:18 +0100912 union gtp_packet packet;
913 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
914 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000915}
916
jjako08d331d2003-10-13 20:33:30 +0000917/* Send off an echo reply */
918int gtp_echo_resp(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +0100919 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000920{
Harald Weltebed35df2011-11-02 13:06:18 +0100921 union gtp_packet packet;
922 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
923 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
924 gsn->restart_counter);
925 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
926 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000927}
928
jjako52c24142002-12-16 13:33:51 +0000929/* Handle a received echo request */
Harald Weltebed35df2011-11-02 13:06:18 +0100930int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
931 int fd, void *pack, unsigned len)
932{
jjako52c24142002-12-16 13:33:51 +0000933
Harald Weltebed35df2011-11-02 13:06:18 +0100934 /* Check if it was a dublicate request */
935 if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
936 return 0;
jjako52c24142002-12-16 13:33:51 +0000937
Harald Weltebed35df2011-11-02 13:06:18 +0100938 /* Send off reply to request */
939 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000940}
941
942/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000943int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
Harald Weltebed35df2011-11-02 13:06:18 +0100944 void *pack, unsigned len)
945{
946 union gtpie_member *ie[GTPIE_SIZE];
947 unsigned char recovery;
948 void *cbp = NULL;
949 uint8_t type = 0;
950 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000951
Harald Weltebed35df2011-11-02 13:06:18 +0100952 /* Remove packet from queue */
953 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
954 return EOF;
jjako52c24142002-12-16 13:33:51 +0000955
Harald Weltebed35df2011-11-02 13:06:18 +0100956 /* Extract information elements into a pointer array */
957 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
958 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100959 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
960 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100961 if (gsn->cb_conf)
962 gsn->cb_conf(type, EOF, NULL, cbp);
963 return EOF;
964 }
jjako52c24142002-12-16 13:33:51 +0000965
Harald Weltebed35df2011-11-02 13:06:18 +0100966 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
967 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +0100968 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
969 "Missing mandatory field\n");
Harald Weltebed35df2011-11-02 13:06:18 +0100970 if (gsn->cb_conf)
971 gsn->cb_conf(type, EOF, NULL, cbp);
972 return EOF;
973 }
jjako52c24142002-12-16 13:33:51 +0000974
Harald Weltebed35df2011-11-02 13:06:18 +0100975 /* Echo reply packages does not have a cause information element */
976 /* Instead we return the recovery number in the callback function */
977 if (gsn->cb_conf)
978 gsn->cb_conf(type, recovery, NULL, cbp);
Harald Welte629e9862010-12-24 20:58:09 +0100979
Harald Weltebed35df2011-11-02 13:06:18 +0100980 if (gsn->cb_recovery)
981 gsn->cb_recovery(peer, recovery);
982
983 return 0;
jjako52c24142002-12-16 13:33:51 +0000984}
985
986/* Send off a Version Not Supported message */
987/* This message is somewhat special in that it actually is a
988 * response to some other message with unsupported GTP version
989 * For this reason it has parameters like a response, and does
990 * its own message transmission. No signalling queue is used
991 * The reply is sent to the peer IP and peer UDP. This means that
992 * the peer will be receiving a GTP0 message on a GTP1 port!
993 * In practice however this will never happen as a GTP0 GSN will
994 * only listen to the GTP0 port, and therefore will never receive
995 * anything else than GTP0 */
996
jjako08d331d2003-10-13 20:33:30 +0000997int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
998 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000999{
Harald Weltebed35df2011-11-02 13:06:18 +01001000 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +00001001
Harald Weltebed35df2011-11-02 13:06:18 +01001002 /* GTP 1 is the highest supported protocol */
1003 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
1004 return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +00001005}
1006
1007/* Handle a Version Not Supported message */
Harald Weltebed35df2011-11-02 13:06:18 +01001008int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1009 void *pack, unsigned len)
1010{
jjako52c24142002-12-16 13:33:51 +00001011
Harald Weltebed35df2011-11-02 13:06:18 +01001012 if (gsn->cb_unsup_ind)
1013 gsn->cb_unsup_ind(peer);
1014
1015 return 0;
jjako52c24142002-12-16 13:33:51 +00001016}
1017
jjako2c381332003-10-21 19:09:53 +00001018/* Send off an Supported Extension Headers Notification */
1019int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
1020 int fd, void *pack, unsigned len)
1021{
Harald Weltebed35df2011-11-02 13:06:18 +01001022 union gtp_packet packet;
1023 unsigned int length =
1024 get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
jjako2c381332003-10-21 19:09:53 +00001025
Harald Weltebed35df2011-11-02 13:06:18 +01001026 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
jjako2c381332003-10-21 19:09:53 +00001027
Harald Weltebed35df2011-11-02 13:06:18 +01001028 if (version < 1)
1029 return 0;
jjako2c381332003-10-21 19:09:53 +00001030
Harald Weltebed35df2011-11-02 13:06:18 +01001031 /* We report back that we support only PDCP PDU headers */
1032 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
1033 sizeof(pdcp_pdu), &pdcp_pdu);
jjako2c381332003-10-21 19:09:53 +00001034
Harald Weltebed35df2011-11-02 13:06:18 +01001035 return gtp_notification(gsn, version, &packet, length,
1036 peer, fd, get_seq(pack));
jjako2c381332003-10-21 19:09:53 +00001037}
1038
1039/* Handle a Supported Extension Headers Notification */
Harald Weltebed35df2011-11-02 13:06:18 +01001040int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
1041 void *pack, unsigned len)
1042{
jjako2c381332003-10-21 19:09:53 +00001043
Harald Weltebed35df2011-11-02 13:06:18 +01001044 if (gsn->cb_extheader_ind)
1045 gsn->cb_extheader_ind(peer);
1046
1047 return 0;
jjako2c381332003-10-21 19:09:53 +00001048}
1049
jjako52c24142002-12-16 13:33:51 +00001050/* ***********************************************************
1051 * Session management messages
1052 * Messages: create, update and delete PDP context
1053 *
1054 * Information storage
1055 * Information storage for each PDP context is defined in
1056 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1057 * PDP-address (IP address), sequence numbers, charging ID.
1058 * For the SGSN it also includes radio related mobility
1059 * information.
1060 *************************************************************/
1061
Harald Welte7b3347b2010-05-15 12:18:46 +02001062/* API: Send Create PDP Context Request (7.3.1) */
Harald Weltebed35df2011-11-02 13:06:18 +01001063extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1064 void *cbp)
1065{
1066 union gtp_packet packet;
1067 unsigned int length =
1068 get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1069 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001070
Harald Weltebed35df2011-11-02 13:06:18 +01001071 /* TODO: Secondary PDP Context Activation Procedure */
1072 /* In secondary activation procedure the PDP context is identified
1073 by tei in the header. The following fields are omitted: Selection
1074 mode, IMSI, MSISDN, End User Address, Access Point Name and
1075 Protocol Configuration Options */
jjako2c381332003-10-21 19:09:53 +00001076
Harald Weltebed35df2011-11-02 13:06:18 +01001077 if (pdp->secondary) {
1078 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001079 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001080 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01001081 return EOF;
1082 }
1083 }
jjako2c381332003-10-21 19:09:53 +00001084
Harald Weltebed35df2011-11-02 13:06:18 +01001085 if (pdp->version == 0) {
1086 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1087 sizeof(pdp->qos_req0), pdp->qos_req0);
1088 }
jjako52c24142002-12-16 13:33:51 +00001089
Harald Weltebed35df2011-11-02 13:06:18 +01001090 /* Section 7.7.2 */
1091 if (pdp->version == 1) {
1092 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1093 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1094 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1095 }
jjako52c24142002-12-16 13:33:51 +00001096
Harald Weltebed35df2011-11-02 13:06:18 +01001097 /* Section 7.7.3 Routing Area Information */
1098 if (pdp->rai_given == 1)
1099 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
1100 pdp->rai.l, (uint8_t *) & pdp->rai.v);
Harald Welte41af5692011-10-07 18:42:34 +02001101
Harald Weltebed35df2011-11-02 13:06:18 +01001102 /* Section 7.7.11 */
1103 if (pdp->norecovery_given == 0)
1104 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1105 gsn->restart_counter);
Harald Welte41af5692011-10-07 18:42:34 +02001106
Harald Weltebed35df2011-11-02 13:06:18 +01001107 /* Section 7.7.12 */
1108 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1109 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1110 pdp->selmode);
jjako2c381332003-10-21 19:09:53 +00001111
Harald Weltebed35df2011-11-02 13:06:18 +01001112 if (pdp->version == 0) {
1113 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1114 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1115 }
jjako08d331d2003-10-13 20:33:30 +00001116
Harald Weltebed35df2011-11-02 13:06:18 +01001117 /* Section 7.7.13 */
1118 if (pdp->version == 1) {
1119 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1120 pdp->teid_own);
jjako08d331d2003-10-13 20:33:30 +00001121
Harald Weltebed35df2011-11-02 13:06:18 +01001122 /* Section 7.7.14 */
1123 if (!pdp->teic_confirmed)
1124 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1125 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001126
Harald Weltebed35df2011-11-02 13:06:18 +01001127 /* Section 7.7.17 */
1128 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001129
Harald Weltebed35df2011-11-02 13:06:18 +01001130 /* Section 7.7.17 */
1131 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1132 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1133 linked_pdp->nsapi);
jjako08d331d2003-10-13 20:33:30 +00001134
Harald Weltebed35df2011-11-02 13:06:18 +01001135 /* Section 7.7.23 */
1136 if (pdp->cch_pdp) /* Only include charging if flags are set */
1137 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1138 pdp->cch_pdp);
1139 }
jjako9b4971d2004-05-27 20:30:19 +00001140
Harald Weltebed35df2011-11-02 13:06:18 +01001141 /* TODO
1142 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1143 pdp->traceref);
1144 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1145 pdp->tracetype); */
jjako08d331d2003-10-13 20:33:30 +00001146
Harald Weltebed35df2011-11-02 13:06:18 +01001147 /* Section 7.7.27 */
1148 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1149 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1150 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001151
Harald Weltebed35df2011-11-02 13:06:18 +01001152 /* Section 7.7.30 */
1153 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1154 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1155 pdp->apn_use.l, pdp->apn_use.v);
jjako08d331d2003-10-13 20:33:30 +00001156
Harald Weltebed35df2011-11-02 13:06:18 +01001157 /* Section 7.7.31 */
1158 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1159 if (pdp->pco_req.l)
1160 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1161 pdp->pco_req.l, pdp->pco_req.v);
jjako2c381332003-10-21 19:09:53 +00001162
Harald Weltebed35df2011-11-02 13:06:18 +01001163 /* Section 7.7.32 */
1164 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1165 pdp->gsnlc.l, pdp->gsnlc.v);
1166 /* Section 7.7.32 */
1167 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1168 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001169
Harald Weltebed35df2011-11-02 13:06:18 +01001170 /* Section 7.7.33 */
1171 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1172 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1173 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001174
Harald Weltebed35df2011-11-02 13:06:18 +01001175 /* Section 7.7.34 */
1176 if (pdp->version == 1)
1177 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1178 pdp->qos_req.l, pdp->qos_req.v);
jjako08d331d2003-10-13 20:33:30 +00001179
Harald Weltebed35df2011-11-02 13:06:18 +01001180 /* Section 7.7.36 */
1181 if ((pdp->version == 1) && pdp->tft.l)
1182 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1183 pdp->tft.l, pdp->tft.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001184
Harald Weltebed35df2011-11-02 13:06:18 +01001185 /* Section 7.7.41 */
1186 if ((pdp->version == 1) && pdp->triggerid.l)
1187 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1188 pdp->triggerid.l, pdp->triggerid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001189
Harald Weltebed35df2011-11-02 13:06:18 +01001190 /* Section 7.7.42 */
1191 if ((pdp->version == 1) && pdp->omcid.l)
1192 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1193 pdp->omcid.l, pdp->omcid.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001194
Harald Weltebed35df2011-11-02 13:06:18 +01001195 /* new R7 fields */
1196 if (pdp->rattype_given == 1)
1197 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE,
1198 pdp->rattype.l, pdp->rattype.v);
Yann BONNAMY944dce32010-10-29 17:07:44 +02001199
Harald Weltebed35df2011-11-02 13:06:18 +01001200 if (pdp->userloc_given == 1)
1201 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC,
1202 pdp->userloc.l, pdp->userloc.v);
jjako52c24142002-12-16 13:33:51 +00001203
Harald Weltebed35df2011-11-02 13:06:18 +01001204 if (pdp->mstz_given == 1)
1205 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ,
1206 pdp->mstz.l, pdp->mstz.v);
1207
1208 if (pdp->imeisv_given == 1)
1209 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV,
1210 pdp->imeisv.l, pdp->imeisv.v);
1211
1212 /* TODO hisaddr0 */
1213 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1214
1215 return 0;
jjako52c24142002-12-16 13:33:51 +00001216}
1217
jjako08d331d2003-10-13 20:33:30 +00001218/* API: Application response to context indication */
Harald Weltebed35df2011-11-02 13:06:18 +01001219int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
1220{
jjako08d331d2003-10-13 20:33:30 +00001221
Harald Weltebed35df2011-11-02 13:06:18 +01001222 /* Now send off a reply to the peer */
1223 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1224
1225 if (cause != GTPCAUSE_ACC_REQ) {
1226 pdp_freepdp(pdp);
1227 }
1228
1229 return 0;
jjako08d331d2003-10-13 20:33:30 +00001230}
1231
1232/* API: Register create context indication callback */
1233int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
Harald Weltebed35df2011-11-02 13:06:18 +01001234 int (*cb_create_context_ind) (struct pdp_t *
1235 pdp))
jjako52c24142002-12-16 13:33:51 +00001236{
Harald Weltebed35df2011-11-02 13:06:18 +01001237 gsn->cb_create_context_ind = cb_create_context_ind;
1238 return 0;
jjako08d331d2003-10-13 20:33:30 +00001239}
1240
jjako08d331d2003-10-13 20:33:30 +00001241/* Send Create PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001242int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1243 uint8_t cause)
1244{
1245 union gtp_packet packet;
1246 unsigned int length =
1247 get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001248
Harald Weltebed35df2011-11-02 13:06:18 +01001249 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001250
Harald Weltebed35df2011-11-02 13:06:18 +01001251 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001252
Harald Weltebed35df2011-11-02 13:06:18 +01001253 if (version == 0)
1254 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1255 sizeof(pdp->qos_neg0), pdp->qos_neg0);
jjako08d331d2003-10-13 20:33:30 +00001256
Harald Weltebed35df2011-11-02 13:06:18 +01001257 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1258 pdp->reorder);
1259 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1260 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001261
Harald Weltebed35df2011-11-02 13:06:18 +01001262 if (version == 0) {
1263 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1264 pdp->fllu);
1265 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1266 pdp->fllc);
1267 }
jjako08d331d2003-10-13 20:33:30 +00001268
Harald Weltebed35df2011-11-02 13:06:18 +01001269 if (version == 1) {
1270 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1271 pdp->teid_own);
1272 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1273 pdp->teic_own);
1274 }
jjako08d331d2003-10-13 20:33:30 +00001275
Harald Weltebed35df2011-11-02 13:06:18 +01001276 /* TODO: We use teic_own as charging ID */
1277 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1278 pdp->teic_own);
jjako2c381332003-10-21 19:09:53 +00001279
Harald Weltebed35df2011-11-02 13:06:18 +01001280 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1281 pdp->eua.l, pdp->eua.v);
jjako52c24142002-12-16 13:33:51 +00001282
Harald Weltebed35df2011-11-02 13:06:18 +01001283 if (pdp->pco_neg.l) { /* Optional PCO */
1284 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1285 pdp->pco_neg.l, pdp->pco_neg.v);
1286 }
jjako52c24142002-12-16 13:33:51 +00001287
Harald Weltebed35df2011-11-02 13:06:18 +01001288 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1289 pdp->gsnlc.l, pdp->gsnlc.v);
1290 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1291 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001292
Harald Weltebed35df2011-11-02 13:06:18 +01001293 if (version == 1)
1294 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1295 pdp->qos_neg.l, pdp->qos_neg.v);
jjako08d331d2003-10-13 20:33:30 +00001296
Harald Weltebed35df2011-11-02 13:06:18 +01001297 /* TODO: Charging gateway address */
1298 }
jjako52c24142002-12-16 13:33:51 +00001299
Harald Weltebed35df2011-11-02 13:06:18 +01001300 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1301 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001302}
1303
1304/* Handle Create PDP Context Request */
1305int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001306 struct sockaddr_in *peer, int fd,
1307 void *pack, unsigned len)
1308{
1309 struct pdp_t *pdp, *pdp_old;
1310 struct pdp_t pdp_buf;
1311 union gtpie_member *ie[GTPIE_SIZE];
1312 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001313
Harald Weltebed35df2011-11-02 13:06:18 +01001314 uint16_t seq = get_seq(pack);
1315 int hlen = get_hlen(pack);
1316 uint8_t linked_nsapi = 0;
1317 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001318
Harald Weltebed35df2011-11-02 13:06:18 +01001319 if (!gtp_dublicate(gsn, version, peer, seq))
1320 return 0;
jjako08d331d2003-10-13 20:33:30 +00001321
Harald Weltebed35df2011-11-02 13:06:18 +01001322 pdp = &pdp_buf;
1323 memset(pdp, 0, sizeof(struct pdp_t));
jjako08d331d2003-10-13 20:33:30 +00001324
Harald Weltebed35df2011-11-02 13:06:18 +01001325 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01001326 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
1327
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01001328 pdp_set_imsi_nsapi(pdp, tid);
Harald Weltebed35df2011-11-02 13:06:18 +01001329 }
jjako52c24142002-12-16 13:33:51 +00001330
Harald Weltebed35df2011-11-02 13:06:18 +01001331 pdp->seq = seq;
1332 pdp->sa_peer = *peer;
1333 pdp->fd = fd;
1334 pdp->version = version;
jjako08d331d2003-10-13 20:33:30 +00001335
Harald Weltebed35df2011-11-02 13:06:18 +01001336 /* Decode information elements */
1337 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1338 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001339 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1340 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001341 if (0 == version)
1342 return EOF;
1343 else
1344 return gtp_create_pdp_resp(gsn, version, pdp,
1345 GTPCAUSE_INVALID_MESSAGE);
1346 }
jjako52c24142002-12-16 13:33:51 +00001347
Harald Weltebed35df2011-11-02 13:06:18 +01001348 if (version == 1) {
1349 /* Linked NSAPI (conditional) */
1350 /* If included this is the Secondary PDP Context Activation Procedure */
1351 /* In secondary activation IMSI is not included, so the context must be */
1352 /* identified by the tei */
1353 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
jjako2c381332003-10-21 19:09:53 +00001354
Harald Weltebed35df2011-11-02 13:06:18 +01001355 /* Find the primary PDP context */
1356 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1357 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001358 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001359 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001360 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001361 return gtp_create_pdp_resp(gsn, version, pdp,
1362 GTPCAUSE_OPT_IE_INCORRECT);
1363 }
jjako2c381332003-10-21 19:09:53 +00001364
Harald Weltebed35df2011-11-02 13:06:18 +01001365 /* Check that the primary PDP context matches linked nsapi */
1366 if (linked_pdp->nsapi != linked_nsapi) {
1367 gsn->incorrect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001368 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001369 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001370 "Incorrect optional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001371 return gtp_create_pdp_resp(gsn, version, pdp,
1372 GTPCAUSE_OPT_IE_INCORRECT);
1373 }
jjako52c24142002-12-16 13:33:51 +00001374
Harald Weltebed35df2011-11-02 13:06:18 +01001375 /* Copy parameters from primary context */
1376 pdp->selmode = linked_pdp->selmode;
1377 pdp->imsi = linked_pdp->imsi;
1378 pdp->msisdn = linked_pdp->msisdn;
1379 pdp->eua = linked_pdp->eua;
1380 pdp->pco_req = linked_pdp->pco_req;
1381 pdp->apn_req = linked_pdp->apn_req;
1382 pdp->teic_gn = linked_pdp->teic_gn;
1383 pdp->secondary = 1;
1384 }
1385 }
1386 /* if (version == 1) */
1387 if (version == 0) {
1388 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1389 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1390 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001391 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1392 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001393 return gtp_create_pdp_resp(gsn, version, pdp,
1394 GTPCAUSE_MAN_IE_MISSING);
1395 }
1396 }
jjako08d331d2003-10-13 20:33:30 +00001397
Harald Weltebed35df2011-11-02 13:06:18 +01001398 if ((version == 1) && (!linked_pdp)) {
1399 /* Not Secondary PDP Context Activation Procedure */
1400 /* IMSI (conditional) */
1401 if (gtpie_gettv0
1402 (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1403 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001404 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1405 len, "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 }
jjako52c24142002-12-16 13:33:51 +00001410
Harald Weltebed35df2011-11-02 13:06:18 +01001411 /* Recovery (optional) */
1412 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1413 if (gsn->cb_recovery)
1414 gsn->cb_recovery(peer, recovery);
1415 }
jjako52c24142002-12-16 13:33:51 +00001416
Harald Weltebed35df2011-11-02 13:06:18 +01001417 /* Selection mode (conditional) */
1418 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1419 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1420 &pdp->selmode, sizeof(pdp->selmode))) {
1421 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001422 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1423 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001424 return gtp_create_pdp_resp(gsn, version, pdp,
1425 GTPCAUSE_MAN_IE_MISSING);
1426 }
1427 }
jjako52c24142002-12-16 13:33:51 +00001428
Harald Weltebed35df2011-11-02 13:06:18 +01001429 if (version == 0) {
1430 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1431 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001432 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1433 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001434 return gtp_create_pdp_resp(gsn, version, pdp,
1435 GTPCAUSE_MAN_IE_MISSING);
1436 }
jjako52c24142002-12-16 13:33:51 +00001437
Harald Weltebed35df2011-11-02 13:06:18 +01001438 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1439 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001440 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1441 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001442 return gtp_create_pdp_resp(gsn, version, pdp,
1443 GTPCAUSE_MAN_IE_MISSING);
1444 }
1445 }
jjako08d331d2003-10-13 20:33:30 +00001446
Harald Weltebed35df2011-11-02 13:06:18 +01001447 if (version == 1) {
1448 /* TEID (mandatory) */
1449 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1450 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001451 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1452 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001453 return gtp_create_pdp_resp(gsn, version, pdp,
1454 GTPCAUSE_MAN_IE_MISSING);
1455 }
jjako2c381332003-10-21 19:09:53 +00001456
Harald Weltebed35df2011-11-02 13:06:18 +01001457 /* TEIC (conditional) */
1458 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1459 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1460 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001461 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001462 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001463 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001464 return gtp_create_pdp_resp(gsn, version, pdp,
1465 GTPCAUSE_MAN_IE_MISSING);
1466 }
1467 }
jjako08d331d2003-10-13 20:33:30 +00001468
Harald Weltebed35df2011-11-02 13:06:18 +01001469 /* NSAPI (mandatory) */
1470 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1471 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001472 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1473 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001474 return gtp_create_pdp_resp(gsn, version, pdp,
1475 GTPCAUSE_MAN_IE_MISSING);
1476 }
1477 }
jjako2e840a32003-01-28 16:05:18 +00001478
Harald Weltebed35df2011-11-02 13:06:18 +01001479 /* Charging Characteriatics (optional) */
1480 /* Trace reference (optional) */
1481 /* Trace type (optional) */
1482 /* Charging Characteriatics (optional) */
jjako52c24142002-12-16 13:33:51 +00001483
Harald Weltebed35df2011-11-02 13:06:18 +01001484 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1485 /* End User Address (conditional) */
1486 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1487 &pdp->eua.v, sizeof(pdp->eua.v))) {
1488 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001489 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1490 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001491 return gtp_create_pdp_resp(gsn, version, pdp,
1492 GTPCAUSE_MAN_IE_MISSING);
1493 }
jjako08d331d2003-10-13 20:33:30 +00001494
Harald Weltebed35df2011-11-02 13:06:18 +01001495 /* APN */
1496 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1497 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1498 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001499 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1500 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001501 return gtp_create_pdp_resp(gsn, version, pdp,
1502 GTPCAUSE_MAN_IE_MISSING);
1503 }
jjako2c381332003-10-21 19:09:53 +00001504
Harald Weltebed35df2011-11-02 13:06:18 +01001505 /* Extract protocol configuration options (optional) */
1506 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1507 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1508 }
1509 }
jjako2c381332003-10-21 19:09:53 +00001510
Harald Weltebed35df2011-11-02 13:06:18 +01001511 /* SGSN address for signalling (mandatory) */
1512 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1513 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1514 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001515 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1516 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001517 return gtp_create_pdp_resp(gsn, version, pdp,
1518 GTPCAUSE_MAN_IE_MISSING);
1519 }
jjako2e840a32003-01-28 16:05:18 +00001520
Harald Weltebed35df2011-11-02 13:06:18 +01001521 /* SGSN address for user traffic (mandatory) */
1522 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1523 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1524 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001525 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1526 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001527 return gtp_create_pdp_resp(gsn, version, pdp,
1528 GTPCAUSE_MAN_IE_MISSING);
1529 }
jjako52c24142002-12-16 13:33:51 +00001530
Harald Weltebed35df2011-11-02 13:06:18 +01001531 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1532 /* MSISDN (conditional) */
1533 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1534 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1535 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001536 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1537 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001538 return gtp_create_pdp_resp(gsn, version, pdp,
1539 GTPCAUSE_MAN_IE_MISSING);
1540 }
1541 }
jjako52c24142002-12-16 13:33:51 +00001542
Harald Weltebed35df2011-11-02 13:06:18 +01001543 if (version == 1) {
1544 /* QoS (mandatory) */
1545 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1546 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1547 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001548 GTP_LOGPKG(LOGL_ERROR, peer, pack,
1549 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001550 return gtp_create_pdp_resp(gsn, version, pdp,
1551 GTPCAUSE_MAN_IE_MISSING);
1552 }
1553
1554 /* TFT (conditional) */
1555 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1556 &pdp->tft.v, sizeof(pdp->tft.v))) {
1557 }
1558
1559 /* Trigger ID */
1560 /* OMC identity */
1561 }
1562
1563 /* Initialize our own IP addresses */
1564 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1565 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1566
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001567 DEBUGP(DLGTP, "gtp_create_pdp_ind: Before pdp_tidget\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001568
1569 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1570 /* Found old pdp with same tid. Now the voodoo begins! */
1571 /* 09.60 / 29.060 allows create on existing context to "steal" */
1572 /* the context which was allready established */
1573 /* We check that the APN, selection mode and MSISDN is the same */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001574 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001575 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1576 &&
1577 (!memcmp
1578 (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1579 && (pdp->selmode == pdp_old->selmode)
1580 && (pdp->msisdn.l == pdp_old->msisdn.l)
1581 &&
1582 (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
1583 {
1584 /* OK! We are dealing with the same APN. We will copy new
1585 * parameters to the old pdp and send off confirmation
1586 * We ignore the following information elements:
1587 * QoS: MS will get originally negotiated QoS.
1588 * End user address (EUA). MS will get old EUA anyway.
1589 * Protocol configuration option (PCO): Only application can verify */
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001590 DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001591
1592 /* Copy remote flow label */
1593 pdp_old->flru = pdp->flru;
1594 pdp_old->flrc = pdp->flrc;
1595
1596 /* Copy remote tei */
1597 pdp_old->teid_gn = pdp->teid_gn;
1598 pdp_old->teic_gn = pdp->teic_gn;
1599
1600 /* Copy peer GSN address */
1601 pdp_old->gsnrc.l = pdp->gsnrc.l;
1602 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1603 pdp_old->gsnru.l = pdp->gsnru.l;
1604 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1605
1606 /* Copy request parameters */
1607 pdp_old->seq = pdp->seq;
1608 pdp_old->sa_peer = pdp->sa_peer;
1609 pdp_old->fd = pdp->fd = fd;
1610 pdp_old->version = pdp->version = version;
1611
1612 /* Switch to using the old pdp context */
1613 pdp = pdp_old;
1614
1615 /* Confirm to peer that things were "successful" */
1616 return gtp_create_pdp_resp(gsn, version, pdp,
1617 GTPCAUSE_ACC_REQ);
1618 } else { /* This is not the same PDP context. Delete the old one. */
1619
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001620 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleting old context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001621
1622 if (gsn->cb_delete_context)
1623 gsn->cb_delete_context(pdp_old);
1624 pdp_freepdp(pdp_old);
1625
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001626 DEBUGP(DLGTP, "gtp_create_pdp_ind: Deleted...\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001627 }
1628 }
1629
1630 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
Harald Weltee257be12017-08-12 14:55:09 +02001631 if (pdp)
1632 pdp->gsn = gsn;
Harald Weltebed35df2011-11-02 13:06:18 +01001633
1634 /* Callback function to validata login */
1635 if (gsn->cb_create_context_ind != 0)
1636 return gsn->cb_create_context_ind(pdp);
1637 else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001638 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1639 "No create_context_ind callback defined\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001640 return gtp_create_pdp_resp(gsn, version, pdp,
1641 GTPCAUSE_NOT_SUPPORTED);
1642 }
jjako52c24142002-12-16 13:33:51 +00001643}
1644
jjako52c24142002-12-16 13:33:51 +00001645/* Handle Create PDP Context Response */
1646int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01001647 struct sockaddr_in *peer, void *pack, unsigned len)
1648{
1649 struct pdp_t *pdp;
1650 union gtpie_member *ie[GTPIE_SIZE];
1651 uint8_t cause, recovery;
1652 void *cbp = NULL;
1653 uint8_t type = 0;
1654 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001655
Harald Weltebed35df2011-11-02 13:06:18 +01001656 /* Remove packet from queue */
1657 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
1658 return EOF;
jjako52c24142002-12-16 13:33:51 +00001659
Harald Weltebed35df2011-11-02 13:06:18 +01001660 /* Find the context in question */
1661 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1662 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001663 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01001664 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01001665 if (gsn->cb_conf)
1666 gsn->cb_conf(type, EOF, NULL, cbp);
1667 return EOF;
1668 }
jjako2c381332003-10-21 19:09:53 +00001669
Harald Weltebed35df2011-11-02 13:06:18 +01001670 /* Register that we have received a valid teic from GGSN */
1671 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00001672
Harald Weltebed35df2011-11-02 13:06:18 +01001673 /* Decode information elements */
1674 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
1675 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001676 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1677 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001678 if (gsn->cb_conf)
1679 gsn->cb_conf(type, EOF, pdp, cbp);
1680 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1681 pdp_freepdp(pdp); */
1682 return EOF;
1683 }
jjako52c24142002-12-16 13:33:51 +00001684
Harald Weltebed35df2011-11-02 13:06:18 +01001685 /* Extract cause value (mandatory) */
1686 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1687 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001688 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
1689 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001690 if (gsn->cb_conf)
1691 gsn->cb_conf(type, EOF, pdp, cbp);
1692 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1693 pdp_freepdp(pdp); */
1694 return EOF;
1695 }
jjako52c24142002-12-16 13:33:51 +00001696
Harald Weltebed35df2011-11-02 13:06:18 +01001697 /* Extract recovery (optional) */
1698 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1699 if (gsn->cb_recovery)
1700 gsn->cb_recovery(peer, recovery);
1701 }
jjako52c24142002-12-16 13:33:51 +00001702
Harald Weltebed35df2011-11-02 13:06:18 +01001703 /* Extract protocol configuration options (optional) */
1704 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1705 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1706 }
jjako52c24142002-12-16 13:33:51 +00001707
Harald Weltebed35df2011-11-02 13:06:18 +01001708 /* Check all conditional information elements */
1709 if (GTPCAUSE_ACC_REQ == cause) {
jjako52c24142002-12-16 13:33:51 +00001710
Harald Weltebed35df2011-11-02 13:06:18 +01001711 if (version == 0) {
1712 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1713 &pdp->qos_neg0,
1714 sizeof(pdp->qos_neg0))) {
1715 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001716 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001717 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001718 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001719 if (gsn->cb_conf)
1720 gsn->cb_conf(type, EOF, pdp, cbp);
1721 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1722 pdp_freepdp(pdp); */
1723 return EOF;
1724 }
1725 }
jjako08d331d2003-10-13 20:33:30 +00001726
Harald Weltebed35df2011-11-02 13:06:18 +01001727 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1728 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001729 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001730 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001731 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001732 if (gsn->cb_conf)
1733 gsn->cb_conf(type, EOF, pdp, cbp);
1734 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1735 pdp_freepdp(pdp); */
1736 return EOF;
1737 }
jjako52c24142002-12-16 13:33:51 +00001738
Harald Weltebed35df2011-11-02 13:06:18 +01001739 if (version == 0) {
1740 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1741 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001742 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001743 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001744 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001745 if (gsn->cb_conf)
1746 gsn->cb_conf(type, EOF, pdp, cbp);
1747 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1748 pdp_freepdp(pdp); */
1749 return EOF;
1750 }
jjako52c24142002-12-16 13:33:51 +00001751
Harald Weltebed35df2011-11-02 13:06:18 +01001752 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1753 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001754 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001755 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001756 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001757 if (gsn->cb_conf)
1758 gsn->cb_conf(type, EOF, pdp, cbp);
1759 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1760 pdp_freepdp(pdp); */
1761 return EOF;
1762 }
1763 }
1764
1765 if (version == 1) {
1766 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1767 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001768 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001769 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001770 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001771 if (gsn->cb_conf)
1772 gsn->cb_conf(type, EOF, pdp, cbp);
1773 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1774 pdp_freepdp(pdp); */
1775 return EOF;
1776 }
1777
1778 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1779 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001780 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001781 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001782 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001783 if (gsn->cb_conf)
1784 gsn->cb_conf(type, EOF, pdp, cbp);
1785 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1786 pdp_freepdp(pdp); */
1787 return EOF;
1788 }
1789 }
1790
1791 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1792 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001793 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001794 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001795 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001796 if (gsn->cb_conf)
1797 gsn->cb_conf(type, EOF, pdp, cbp);
1798 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1799 pdp_freepdp(pdp); */
1800 }
1801
1802 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1803 &pdp->eua.v, sizeof(pdp->eua.v))) {
1804 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001805 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001806 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001807 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001808 if (gsn->cb_conf)
1809 gsn->cb_conf(type, EOF, pdp, cbp);
1810 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1811 pdp_freepdp(pdp); */
1812 return EOF;
1813 }
1814
1815 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1816 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1817 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001818 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001819 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001820 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001821 if (gsn->cb_conf)
1822 gsn->cb_conf(type, EOF, pdp, cbp);
1823 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1824 pdp_freepdp(pdp); */
1825 return EOF;
1826 }
1827
1828 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1829 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1830 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001831 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Harald Weltebed35df2011-11-02 13:06:18 +01001832 len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001833 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001834 if (gsn->cb_conf)
1835 gsn->cb_conf(type, EOF, pdp, cbp);
1836 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1837 pdp_freepdp(pdp); */
1838 return EOF;
1839 }
1840
1841 if (version == 1) {
1842 if (gtpie_gettlv
1843 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1844 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1845 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001846 GTP_LOGPKG(LOGL_ERROR, peer,
Harald Weltebed35df2011-11-02 13:06:18 +01001847 pack, len,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01001848 "Missing conditional information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01001849 if (gsn->cb_conf)
1850 gsn->cb_conf(type, EOF, pdp, cbp);
1851 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1852 pdp_freepdp(pdp); */
1853 return EOF;
1854 }
1855 }
1856
1857 }
1858
1859 if (gsn->cb_conf)
1860 gsn->cb_conf(type, cause, pdp, cbp);
1861
1862 return 0;
jjako52c24142002-12-16 13:33:51 +00001863}
1864
jjako08d331d2003-10-13 20:33:30 +00001865/* API: Send Update PDP Context Request */
1866int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01001867 struct in_addr *inetaddr)
1868{
1869 union gtp_packet packet;
1870 unsigned int length =
1871 get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001872
Harald Weltebed35df2011-11-02 13:06:18 +01001873 if (pdp->version == 0)
1874 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1875 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako08d331d2003-10-13 20:33:30 +00001876
Harald Weltebed35df2011-11-02 13:06:18 +01001877 /* Include IMSI if updating with unknown teic_gn */
1878 if ((pdp->version == 1) && (!pdp->teic_gn))
1879 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1880 sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
1881
1882 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1883 gsn->restart_counter);
1884
1885 if (pdp->version == 0) {
1886 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
1887 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
1888 }
1889
1890 if (pdp->version == 1) {
1891 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1892 pdp->teid_own);
1893
1894 if (!pdp->teic_confirmed)
1895 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1896 pdp->teic_own);
1897 }
1898
1899 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
1900
1901 /* TODO
1902 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1903 pdp->traceref);
1904 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1905 pdp->tracetype); */
1906
1907 /* TODO if ggsn update message
1908 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1909 pdp->eua.l, pdp->eua.v);
1910 */
1911
1912 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1913 pdp->gsnlc.l, pdp->gsnlc.v);
1914 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1915 pdp->gsnlu.l, pdp->gsnlu.v);
1916
1917 if (pdp->version == 1)
1918 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1919 pdp->qos_req.l, pdp->qos_req.v);
1920
1921 if ((pdp->version == 1) && pdp->tft.l)
1922 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1923 pdp->tft.l, pdp->tft.v);
1924
1925 if ((pdp->version == 1) && pdp->triggerid.l)
1926 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1927 pdp->triggerid.l, pdp->triggerid.v);
1928
1929 if ((pdp->version == 1) && pdp->omcid.l)
1930 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1931 pdp->omcid.l, pdp->omcid.v);
1932
Daniel Willmann134a7752016-02-03 18:53:29 +01001933 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
Harald Weltebed35df2011-11-02 13:06:18 +01001934
1935 return 0;
jjako52c24142002-12-16 13:33:51 +00001936}
1937
jjako08d331d2003-10-13 20:33:30 +00001938/* Send Update PDP Context Response */
Harald Weltebed35df2011-11-02 13:06:18 +01001939int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1940 struct sockaddr_in *peer, int fd,
jjako08d331d2003-10-13 20:33:30 +00001941 void *pack, unsigned len,
Harald Weltebed35df2011-11-02 13:06:18 +01001942 struct pdp_t *pdp, uint8_t cause)
1943{
jjako08d331d2003-10-13 20:33:30 +00001944
Harald Weltebed35df2011-11-02 13:06:18 +01001945 union gtp_packet packet;
1946 unsigned int length =
1947 get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
jjako08d331d2003-10-13 20:33:30 +00001948
Harald Weltebed35df2011-11-02 13:06:18 +01001949 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako08d331d2003-10-13 20:33:30 +00001950
Harald Weltebed35df2011-11-02 13:06:18 +01001951 if (cause == GTPCAUSE_ACC_REQ) {
1952
1953 if (version == 0)
1954 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1955 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1956
1957 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1958 gsn->restart_counter);
1959
1960 if (version == 0) {
1961 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1962 pdp->fllu);
1963 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1964 pdp->fllc);
1965 }
1966
1967 if (version == 1) {
1968 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1969 pdp->teid_own);
1970
1971 if (!pdp->teic_confirmed)
1972 gtpie_tv4(&packet, &length, GTP_MAX,
1973 GTPIE_TEI_C, pdp->teic_own);
1974 }
1975
1976 /* TODO we use teid_own as charging ID address */
1977 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1978 pdp->teid_own);
1979
1980 /* If ggsn
1981 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1982 pdp->eua.l, pdp->eua.v); */
1983
1984 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1985 pdp->gsnlc.l, pdp->gsnlc.v);
1986 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1987 pdp->gsnlu.l, pdp->gsnlu.v);
1988
1989 if (version == 1)
1990 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1991 pdp->qos_neg.l, pdp->qos_neg.v);
1992
1993 /* TODO: Charging gateway address */
1994 }
1995
1996 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1997 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001998}
1999
jjako52c24142002-12-16 13:33:51 +00002000/* Handle Update PDP Context Request */
2001int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002002 struct sockaddr_in *peer, int fd,
2003 void *pack, unsigned len)
2004{
2005 struct pdp_t *pdp;
2006 struct pdp_t pdp_backup;
2007 union gtpie_member *ie[GTPIE_SIZE];
2008 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00002009
Harald Weltebed35df2011-11-02 13:06:18 +01002010 uint16_t seq = get_seq(pack);
2011 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002012
Harald Weltebed35df2011-11-02 13:06:18 +01002013 uint64_t imsi;
2014 uint8_t nsapi;
jjako52c24142002-12-16 13:33:51 +00002015
Harald Weltebed35df2011-11-02 13:06:18 +01002016 /* Is this a dublicate ? */
2017 if (!gtp_dublicate(gsn, version, peer, seq)) {
2018 return 0; /* We allready send of response once */
2019 }
jjako08d331d2003-10-13 20:33:30 +00002020
Harald Weltebed35df2011-11-02 13:06:18 +01002021 /* Decode information elements */
2022 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2023 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002024 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2025 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002026 if (0 == version)
2027 return EOF;
2028 else
2029 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2030 len, NULL,
2031 GTPCAUSE_INVALID_MESSAGE);
2032 }
jjako08d331d2003-10-13 20:33:30 +00002033
Harald Weltebed35df2011-11-02 13:06:18 +01002034 /* Finding PDP: */
2035 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
2036 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
2037 /* we have to use the tunnel endpoint identifier */
2038 if (version == 0) {
Pablo Neira Ayuso1a1ba022014-03-20 12:35:26 +01002039 uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid);
2040
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01002041 pdp_set_imsi_nsapi(pdp, tid);
jjako52c24142002-12-16 13:33:51 +00002042
Harald Weltebed35df2011-11-02 13:06:18 +01002043 /* Find the context in question */
2044 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2045 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002046 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2047 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002048 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2049 len, NULL,
2050 GTPCAUSE_NON_EXIST);
2051 }
2052 } else if (version == 1) {
2053 /* NSAPI (mandatory) */
2054 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
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 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2059 len, NULL,
2060 GTPCAUSE_MAN_IE_MISSING);
2061 }
jjako08d331d2003-10-13 20:33:30 +00002062
Harald Weltebed35df2011-11-02 13:06:18 +01002063 /* IMSI (conditional) */
2064 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
2065 /* Find the context in question */
2066 if (pdp_getgtp1(&pdp, get_tei(pack))) {
2067 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002068 GTP_LOGPKG(LOGL_ERROR, peer,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002069 pack, len, "Unknown PDP context: %u\n",
2070 get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002071 return gtp_update_pdp_resp(gsn, version, peer,
2072 fd, pack, len, NULL,
2073 GTPCAUSE_NON_EXIST);
2074 }
2075 } else {
2076 /* Find the context in question */
2077 if (pdp_getimsi(&pdp, imsi, nsapi)) {
2078 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002079 GTP_LOGPKG(LOGL_ERROR, peer,
2080 pack, len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002081 return gtp_update_pdp_resp(gsn, version, peer,
2082 fd, pack, len, NULL,
2083 GTPCAUSE_NON_EXIST);
2084 }
2085 }
2086 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002087 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002088 return EOF;
2089 }
jjako08d331d2003-10-13 20:33:30 +00002090
Harald Weltebed35df2011-11-02 13:06:18 +01002091 /* Make a backup copy in case anything is wrong */
2092 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
jjako08d331d2003-10-13 20:33:30 +00002093
Harald Weltebed35df2011-11-02 13:06:18 +01002094 if (version == 0) {
2095 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2096 pdp->qos_req0, sizeof(pdp->qos_req0))) {
2097 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002098 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2099 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002100 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2101 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2102 len, pdp,
2103 GTPCAUSE_MAN_IE_MISSING);
2104 }
2105 }
jjako52c24142002-12-16 13:33:51 +00002106
Harald Weltebed35df2011-11-02 13:06:18 +01002107 /* Recovery (optional) */
2108 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2109 if (gsn->cb_recovery)
2110 gsn->cb_recovery(peer, recovery);
2111 }
jjako08d331d2003-10-13 20:33:30 +00002112
Harald Weltebed35df2011-11-02 13:06:18 +01002113 if (version == 0) {
2114 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2115 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002116 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2117 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002118 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2119 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2120 len, pdp,
2121 GTPCAUSE_MAN_IE_MISSING);
2122 }
jjako52c24142002-12-16 13:33:51 +00002123
Harald Weltebed35df2011-11-02 13:06:18 +01002124 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2125 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002126 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2127 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002128 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2129 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2130 len, pdp,
2131 GTPCAUSE_MAN_IE_MISSING);
2132 }
2133 }
jjako52c24142002-12-16 13:33:51 +00002134
Harald Weltebed35df2011-11-02 13:06:18 +01002135 if (version == 1) {
2136 /* TEID (mandatory) */
2137 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2138 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002139 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2140 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002141 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2142 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2143 len, pdp,
2144 GTPCAUSE_MAN_IE_MISSING);
2145 }
jjako52c24142002-12-16 13:33:51 +00002146
Harald Weltebed35df2011-11-02 13:06:18 +01002147 /* TEIC (conditional) */
2148 /* If TEIC is not included it means that we have allready received it */
2149 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2150 /* all updated contexts, or only for one of the linked contexts */
2151 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2152
2153 /* NSAPI (mandatory) */
2154 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2155 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002156 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2157 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002158 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2159 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2160 len, pdp,
2161 GTPCAUSE_MAN_IE_MISSING);
2162 }
2163 }
2164
2165 /* Trace reference (optional) */
2166 /* Trace type (optional) */
2167
2168 /* End User Address (conditional) TODO: GGSN Initiated
2169 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2170 &pdp->eua.v, sizeof(pdp->eua.v))) {
2171 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002172 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Harald Weltebed35df2011-11-02 13:06:18 +01002173 "Missing mandatory information field");
2174 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2175 return gtp_update_pdp_resp(gsn, version, pdp,
2176 GTPCAUSE_MAN_IE_MISSING);
2177 } */
2178
2179 /* SGSN address for signalling (mandatory) */
2180 /* It is weird that this is mandatory when TEIC is conditional */
2181 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2182 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2183 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002184 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2185 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002186 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2187 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2188 pdp, GTPCAUSE_MAN_IE_MISSING);
2189 }
2190
2191 /* SGSN address for user traffic (mandatory) */
2192 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2193 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2194 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002195 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2196 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002197 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2198 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
2199 pdp, GTPCAUSE_MAN_IE_MISSING);
2200 }
2201
2202 if (version == 1) {
2203 /* QoS (mandatory) */
2204 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2205 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2206 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002207 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2208 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002209 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2210 return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
2211 len, pdp,
2212 GTPCAUSE_MAN_IE_MISSING);
2213 }
2214
2215 /* TFT (conditional) */
2216 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2217 &pdp->tft.v, sizeof(pdp->tft.v))) {
2218 }
2219
2220 /* OMC identity */
2221 }
2222
2223 /* Confirm to peer that things were "successful" */
2224 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2225 GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00002226}
2227
jjako52c24142002-12-16 13:33:51 +00002228/* Handle Update PDP Context Response */
2229int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002230 struct sockaddr_in *peer, void *pack, unsigned len)
2231{
2232 struct pdp_t *pdp;
2233 union gtpie_member *ie[GTPIE_SIZE];
2234 uint8_t cause, recovery;
2235 void *cbp = NULL;
2236 uint8_t type = 0;
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002237 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002238
Harald Weltebed35df2011-11-02 13:06:18 +01002239 /* Remove packet from queue */
2240 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
2241 return EOF;
jjako52c24142002-12-16 13:33:51 +00002242
Harald Weltebed35df2011-11-02 13:06:18 +01002243 /* Find the context in question */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002244 if (pdp_getgtp1(&pdp, get_tei(pack))) {
Harald Weltebed35df2011-11-02 13:06:18 +01002245 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002246 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002247 "Unknown PDP context: %u\n", get_tei(pack));
Daniel Willmannd9975522016-02-04 15:38:12 +01002248 pdp = NULL;
2249 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002250 }
jjako2c381332003-10-21 19:09:53 +00002251
Harald Weltebed35df2011-11-02 13:06:18 +01002252 /* Register that we have received a valid teic from GGSN */
2253 pdp->teic_confirmed = 1;
jjako52c24142002-12-16 13:33:51 +00002254
Harald Weltebed35df2011-11-02 13:06:18 +01002255 /* Decode information elements */
Daniel Willmann05f3ef32016-02-03 18:53:30 +01002256 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002257 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002258 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2259 "Invalid message format\n");
Daniel Willmannd9975522016-02-04 15:38:12 +01002260 goto err_out;
Harald Weltebed35df2011-11-02 13:06:18 +01002261 }
jjako52c24142002-12-16 13:33:51 +00002262
Harald Weltebed35df2011-11-02 13:06:18 +01002263 /* Extract cause value (mandatory) */
2264 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
Daniel Willmannd9975522016-02-04 15:38:12 +01002265 goto err_missing;
Harald Weltebed35df2011-11-02 13:06:18 +01002266 }
jjako52c24142002-12-16 13:33:51 +00002267
Harald Weltebed35df2011-11-02 13:06:18 +01002268 /* Extract recovery (optional) */
2269 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2270 if (gsn->cb_recovery)
2271 gsn->cb_recovery(peer, recovery);
2272 }
2273
2274 /* Check all conditional information elements */
Daniel Willmannd9975522016-02-04 15:38:12 +01002275 /* TODO: This does not handle GGSN-initiated update responses */
2276 if (GTPCAUSE_ACC_REQ == cause) {
2277 if (version == 0) {
2278 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2279 &pdp->qos_neg0,
2280 sizeof(pdp->qos_neg0))) {
2281 goto err_missing;
2282 }
2283
2284 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
2285 goto err_missing;
2286 }
2287
2288 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
2289 goto err_missing;
2290 }
Harald Weltebed35df2011-11-02 13:06:18 +01002291 }
2292
Daniel Willmannd9975522016-02-04 15:38:12 +01002293 if (version == 1) {
2294 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
2295 goto err_missing;
2296 }
Harald Weltebed35df2011-11-02 13:06:18 +01002297
Daniel Willmannd9975522016-02-04 15:38:12 +01002298 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
2299 goto err_missing;
2300 }
2301 }
2302
2303 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
2304 goto err_missing;
2305 }
2306
2307 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2308 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2309 goto err_missing;
2310 }
2311
2312 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2313 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2314 goto err_missing;
2315 }
2316
2317 if (version == 1) {
2318 if (gtpie_gettlv
2319 (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
2320 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
2321 goto err_missing;
2322 }
2323 }
Harald Weltebed35df2011-11-02 13:06:18 +01002324 }
Daniel Willmannd9975522016-02-04 15:38:12 +01002325
2326 if (gsn->cb_conf)
2327 gsn->cb_conf(type, cause, pdp, cbp);
2328 return 0; /* Succes */
2329
2330err_missing:
2331 gsn->missing++;
2332 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2333 "Missing information field\n");
2334err_out:
2335 if (gsn->cb_conf)
2336 gsn->cb_conf(type, EOF, pdp, cbp);
2337 return EOF;
jjako52c24142002-12-16 13:33:51 +00002338}
2339
jjako08d331d2003-10-13 20:33:30 +00002340/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002341int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
Harald Weltebed35df2011-11-02 13:06:18 +01002342 int teardown)
2343{
2344 union gtp_packet packet;
2345 unsigned int length =
2346 get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2347 struct in_addr addr;
2348 struct pdp_t *linked_pdp;
2349 struct pdp_t *secondary_pdp;
2350 int n;
2351 int count = 0;
jjako2c381332003-10-21 19:09:53 +00002352
Harald Weltebed35df2011-11-02 13:06:18 +01002353 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2354 gsn->err_address++;
Max14b1b632017-08-21 20:14:59 +02002355 LOGP(DLGTP, LOGL_ERROR, "GSN address (len=%u) conversion failed\n", pdp->gsnrc.l);
Harald Weltebed35df2011-11-02 13:06:18 +01002356 return EOF;
jjako2c381332003-10-21 19:09:53 +00002357 }
jjako2c381332003-10-21 19:09:53 +00002358
Harald Weltebed35df2011-11-02 13:06:18 +01002359 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002360 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002361 "Unknown linked PDP context: %u\n", pdp->teic_own);
Harald Weltebed35df2011-11-02 13:06:18 +01002362 return EOF;
2363 }
2364
2365 if (!teardown) {
2366 for (n = 0; n < PDP_MAXNSAPI; n++)
2367 if (linked_pdp->secondary_tei[n])
2368 count++;
2369 if (count <= 1) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002370 LOGP(DLGTP, LOGL_ERROR,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002371 "Must use teardown for last context: %d\n", count);
Harald Weltebed35df2011-11-02 13:06:18 +01002372 return EOF;
2373 }
2374 }
2375
2376 if (pdp->version == 1) {
2377 if (teardown)
2378 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2379 0xff);
2380
2381 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
2382 }
2383
2384 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2385
2386 if (teardown) { /* Remove all contexts */
2387 for (n = 0; n < PDP_MAXNSAPI; n++) {
2388 if (linked_pdp->secondary_tei[n]) {
2389 if (pdp_getgtp1
2390 (&secondary_pdp,
2391 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002392 LOGP(DLGTP, LOGL_ERROR,
2393 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002394 return EOF;
2395 }
2396 if (linked_pdp != secondary_pdp) {
2397 if (gsn->cb_delete_context)
2398 gsn->cb_delete_context
2399 (secondary_pdp);
2400 pdp_freepdp(secondary_pdp);
2401 }
2402 }
2403 }
2404 if (gsn->cb_delete_context)
2405 gsn->cb_delete_context(linked_pdp);
2406 pdp_freepdp(linked_pdp);
2407 } else {
2408 if (gsn->cb_delete_context)
2409 gsn->cb_delete_context(pdp);
2410 if (pdp == linked_pdp) {
2411 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2412 linked_pdp->nodata = 1;
2413 } else
2414 pdp_freepdp(pdp);
2415 }
2416
2417 return 0;
jjako2c381332003-10-21 19:09:53 +00002418}
jjako08d331d2003-10-13 20:33:30 +00002419
jjako52c24142002-12-16 13:33:51 +00002420/* Send Delete PDP Context Response */
2421int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002422 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002423 void *pack, unsigned len,
2424 struct pdp_t *pdp, struct pdp_t *linked_pdp,
jjako2c381332003-10-21 19:09:53 +00002425 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002426{
Harald Weltebed35df2011-11-02 13:06:18 +01002427 union gtp_packet packet;
2428 struct pdp_t *secondary_pdp;
2429 unsigned int length =
2430 get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2431 int n;
jjako52c24142002-12-16 13:33:51 +00002432
Harald Weltebed35df2011-11-02 13:06:18 +01002433 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002434
Harald Weltebed35df2011-11-02 13:06:18 +01002435 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2436 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002437
Harald Weltebed35df2011-11-02 13:06:18 +01002438 if (cause == GTPCAUSE_ACC_REQ) {
2439 if ((teardown) || (version == 0)) { /* Remove all contexts */
2440 for (n = 0; n < PDP_MAXNSAPI; n++) {
2441 if (linked_pdp->secondary_tei[n]) {
2442 if (pdp_getgtp1
2443 (&secondary_pdp,
2444 linked_pdp->secondary_tei[n])) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002445 LOGP(DLGTP, LOGL_ERROR,
2446 "Unknown secondary PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002447 return EOF;
2448 }
2449 if (linked_pdp != secondary_pdp) {
2450 if (gsn->cb_delete_context)
2451 gsn->cb_delete_context
2452 (secondary_pdp);
2453 pdp_freepdp(secondary_pdp);
2454 }
2455 }
2456 }
2457 if (gsn->cb_delete_context)
2458 gsn->cb_delete_context(linked_pdp);
2459 pdp_freepdp(linked_pdp);
2460 } else { /* Remove only current context */
2461 if (gsn->cb_delete_context)
2462 gsn->cb_delete_context(pdp);
2463 if (pdp == linked_pdp) {
2464 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
2465 0;
2466 linked_pdp->nodata = 1;
2467 } else
2468 pdp_freepdp(pdp);
2469 }
jjako2c381332003-10-21 19:09:53 +00002470 }
Harald Weltebed35df2011-11-02 13:06:18 +01002471 /* if (cause == GTPCAUSE_ACC_REQ) */
2472 return 0;
jjako52c24142002-12-16 13:33:51 +00002473}
2474
2475/* Handle Delete PDP Context Request */
2476int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002477 struct sockaddr_in *peer, int fd,
Harald Weltebed35df2011-11-02 13:06:18 +01002478 void *pack, unsigned len)
2479{
2480 struct pdp_t *pdp = NULL;
2481 struct pdp_t *linked_pdp = NULL;
2482 union gtpie_member *ie[GTPIE_SIZE];
jjako52c24142002-12-16 13:33:51 +00002483
Harald Weltebed35df2011-11-02 13:06:18 +01002484 uint16_t seq = get_seq(pack);
2485 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00002486
Harald Weltebed35df2011-11-02 13:06:18 +01002487 uint8_t nsapi;
2488 uint8_t teardown = 0;
2489 int n;
2490 int count = 0;
jjako52c24142002-12-16 13:33:51 +00002491
Harald Weltebed35df2011-11-02 13:06:18 +01002492 /* Is this a dublicate ? */
2493 if (!gtp_dublicate(gsn, version, peer, seq)) {
2494 return 0; /* We allready send off response once */
2495 }
jjako2c381332003-10-21 19:09:53 +00002496
Harald Weltebed35df2011-11-02 13:06:18 +01002497 /* Find the linked context in question */
2498 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2499 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002500 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002501 "Unknown PDP context: %u\n", get_tei(pack));
Harald Weltebed35df2011-11-02 13:06:18 +01002502 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2503 NULL, NULL, GTPCAUSE_NON_EXIST,
2504 teardown);
2505 }
jjako2c381332003-10-21 19:09:53 +00002506
Harald Weltebed35df2011-11-02 13:06:18 +01002507 /* If version 0 this is also the secondary context */
2508 if (version == 0)
2509 pdp = linked_pdp;
jjako2c381332003-10-21 19:09:53 +00002510
Harald Weltebed35df2011-11-02 13:06:18 +01002511 /* Decode information elements */
2512 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2513 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002514 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2515 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002516 if (0 == version)
2517 return EOF;
2518 else
2519 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2520 len, NULL, NULL,
2521 GTPCAUSE_INVALID_MESSAGE,
2522 teardown);
2523 }
2524
2525 if (version == 1) {
2526 /* NSAPI (mandatory) */
2527 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2528 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002529 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2530 len, "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002531 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2532 len, NULL, NULL,
2533 GTPCAUSE_MAN_IE_MISSING,
2534 teardown);
2535 }
2536
2537 /* Find the context in question */
2538 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2539 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002540 GTP_LOGPKG(LOGL_ERROR, peer, pack,
2541 len, "Unknown PDP context\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002542 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
2543 len, NULL, NULL,
2544 GTPCAUSE_NON_EXIST,
2545 teardown);
2546 }
2547
2548 /* Teardown (conditional) */
2549 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2550
2551 if (!teardown) {
2552 for (n = 0; n < PDP_MAXNSAPI; n++)
2553 if (linked_pdp->secondary_tei[n])
2554 count++;
2555 if (count <= 1) {
2556 return 0; /* 29.060 7.3.5 Ignore message */
2557 }
2558 }
2559 }
2560
2561 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2562 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002563}
2564
jjako52c24142002-12-16 13:33:51 +00002565/* Handle Delete PDP Context Response */
2566int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002567 struct sockaddr_in *peer, void *pack, unsigned len)
2568{
2569 union gtpie_member *ie[GTPIE_SIZE];
2570 uint8_t cause;
2571 void *cbp = NULL;
2572 uint8_t type = 0;
2573 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002574
Harald Weltebed35df2011-11-02 13:06:18 +01002575 /* Remove packet from queue */
2576 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
2577 return EOF;
jjako52c24142002-12-16 13:33:51 +00002578
Harald Weltebed35df2011-11-02 13:06:18 +01002579 /* Decode information elements */
2580 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2581 gsn->invalid++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002582 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2583 "Invalid message format\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002584 if (gsn->cb_conf)
2585 gsn->cb_conf(type, EOF, NULL, cbp);
2586 return EOF;
2587 }
2588
2589 /* Extract cause value (mandatory) */
2590 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2591 gsn->missing++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002592 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2593 "Missing mandatory information field\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002594 if (gsn->cb_conf)
2595 gsn->cb_conf(type, EOF, NULL, cbp);
2596 return EOF;
2597 }
2598
2599 /* Check the cause value (again) */
2600 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2601 gsn->err_cause++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002602 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2603 "Unexpected cause value received: %d\n", cause);
Harald Weltebed35df2011-11-02 13:06:18 +01002604 if (gsn->cb_conf)
2605 gsn->cb_conf(type, cause, NULL, cbp);
2606 return EOF;
2607 }
2608
2609 /* Callback function to notify application */
2610 if (gsn->cb_conf)
2611 gsn->cb_conf(type, cause, NULL, cbp);
2612
2613 return 0;
jjako52c24142002-12-16 13:33:51 +00002614}
2615
Harald Welte54d082e2017-08-12 22:43:21 +02002616/* Send Error Indication (response to a GPDU message) - 3GPP TS 29.060 7.3.7 */
jjako52c24142002-12-16 13:33:51 +00002617int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002618 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002619 void *pack, unsigned len)
2620{
Harald Weltebed35df2011-11-02 13:06:18 +01002621 union gtp_packet packet;
2622 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2623
Harald Welte54d082e2017-08-12 22:43:21 +02002624 if (version == 1) {
2625 /* Mandatory 7.7.13 TEI Data I */
2626 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
2627 ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei));
2628
2629 /* Mandatory 7.7.32 GSN Address */
2630 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
2631 sizeof(gsn->gsnu), &gsn->gsnu);
2632 }
2633
Harald Weltebed35df2011-11-02 13:06:18 +01002634 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2635 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002636}
2637
2638/* Handle Error Indication */
2639int gtp_error_ind_conf(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002640 struct sockaddr_in *peer, void *pack, unsigned len)
2641{
Harald Welte37d5b152017-08-12 23:58:29 +02002642 union gtpie_member *ie[GTPIE_SIZE];
Harald Weltebed35df2011-11-02 13:06:18 +01002643 struct pdp_t *pdp;
jjako52c24142002-12-16 13:33:51 +00002644
Harald Weltebed35df2011-11-02 13:06:18 +01002645 /* Find the context in question */
Harald Welte37d5b152017-08-12 23:58:29 +02002646 if (version == 0) {
2647 if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
2648 gsn->err_unknownpdp++;
2649 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2650 "Unknown PDP context\n");
2651 return EOF;
2652 }
2653 } else if (version == 1) {
2654 /* we have to look-up based on the *peer* TEID */
2655 int hlen = get_hlen(pack);
2656 uint32_t teid_gn;
2657
2658 /* Decode information elements */
2659 if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
2660 gsn->invalid++;
2661 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2662 "Invalid message format\n");
2663 return EOF;
2664 }
2665
2666 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
2667 gsn->missing++;
2668 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2669 "Missing mandatory information field\n");
2670 return EOF;
2671 }
2672
2673 if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
2674 gsn->err_unknownpdp++;
2675 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
2676 return EOF;
2677 }
Harald Weltebed35df2011-11-02 13:06:18 +01002678 }
jjako52c24142002-12-16 13:33:51 +00002679
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002680 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
2681 "Received Error Indication\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002682
Harald Weltebd228242017-11-06 03:16:49 +09002683 /* This is obvious from above code, given the semantics of the
2684 * functions above, but Coverity doesn't figure this out, so
2685 * let's make it clear. It's good style anyway in case above
2686 * code should ever change. */
2687 OSMO_ASSERT(pdp);
2688
Harald Weltebed35df2011-11-02 13:06:18 +01002689 if (gsn->cb_delete_context)
2690 gsn->cb_delete_context(pdp);
2691 pdp_freepdp(pdp);
2692 return 0;
jjako52c24142002-12-16 13:33:51 +00002693}
2694
2695int gtp_gpdu_ind(struct gsn_t *gsn, int version,
Harald Weltebed35df2011-11-02 13:06:18 +01002696 struct sockaddr_in *peer, int fd, void *pack, unsigned len)
2697{
jjako08d331d2003-10-13 20:33:30 +00002698
Harald Weltebed35df2011-11-02 13:06:18 +01002699 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002700
Harald Weltebed35df2011-11-02 13:06:18 +01002701 /* Need to include code to verify packet src and dest addresses */
2702 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002703
Harald Weltebed35df2011-11-02 13:06:18 +01002704 if (version == 0) {
2705 if (pdp_getgtp0
2706 (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
2707 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002708 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002709 len, "Unknown PDP context, GTPv0\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002710 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2711 len);
2712 }
2713 hlen = GTP0_HEADER_SIZE;
2714 } else if (version == 1) {
2715 if (pdp_getgtp1
2716 (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
2717 gsn->err_unknownpdp++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002718 GTP_LOGPKG(LOGL_ERROR, peer, pack,
Max14b1b632017-08-21 20:14:59 +02002719 len, "Unknown PDP context, GTPv1\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002720 return gtp_error_ind_resp(gsn, version, peer, fd, pack,
2721 len);
2722 }
jjako08d331d2003-10-13 20:33:30 +00002723
Harald Weltebed35df2011-11-02 13:06:18 +01002724 /* Is this a long or a short header ? */
2725 if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
2726 hlen = GTP1_HEADER_SIZE_LONG;
2727 else
2728 hlen = GTP1_HEADER_SIZE_SHORT;
2729 } else {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002730 GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002731 "Unknown version: %d\n", version);
Harald Weltebed35df2011-11-02 13:06:18 +01002732 }
jjako08d331d2003-10-13 20:33:30 +00002733
Harald Weltebed35df2011-11-02 13:06:18 +01002734 /* If the GPDU was not from the peer GSN tell him to delete context */
2735 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2736 gsn->err_unknownpdp++;
Max14b1b632017-08-21 20:14:59 +02002737 GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown GSN peer %s\n", inet_ntoa(peer->sin_addr));
Harald Weltebed35df2011-11-02 13:06:18 +01002738 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2739 }
jjako52c24142002-12-16 13:33:51 +00002740
Harald Weltebed35df2011-11-02 13:06:18 +01002741 /* Callback function */
2742 if (gsn->cb_data_ind != 0)
2743 return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
2744
2745 return 0;
jjako52c24142002-12-16 13:33:51 +00002746}
2747
jjako52c24142002-12-16 13:33:51 +00002748/* Receives GTP packet and sends off for further processing
2749 * Function will check the validity of the header. If the header
2750 * is not valid the packet is either dropped or a version not
2751 * supported is returned to the peer.
2752 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002753int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002754{
Harald Weltebed35df2011-11-02 13:06:18 +01002755 unsigned char buffer[PACKET_MAX];
2756 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002757 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002758 int status;
2759 struct gtp0_header *pheader;
2760 int version = 0; /* GTP version should be determined from header! */
2761 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002762
Harald Weltebed35df2011-11-02 13:06:18 +01002763 /* TODO: Need strategy of userspace buffering and blocking */
2764 /* Currently read is non-blocking and send is blocking. */
2765 /* This means that the program have to wait for busy send calls... */
jjako52c24142002-12-16 13:33:51 +00002766
Harald Weltebed35df2011-11-02 13:06:18 +01002767 while (1) { /* Loop until no more to read */
2768 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002769 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002770 return -1;
2771 }
2772 peerlen = sizeof(peer);
2773 if ((status =
2774 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2775 (struct sockaddr *)&peer, &peerlen)) < 0) {
2776 if (errno == EAGAIN)
2777 return 0;
2778 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002779 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002780 "recvfrom(fd0=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002781 gsn->fd0, (unsigned long)buffer, sizeof(buffer),
2782 status, status ? strerror(errno) : "No error");
2783 return -1;
2784 }
jjako1db1c812003-07-06 20:53:57 +00002785
Harald Weltebed35df2011-11-02 13:06:18 +01002786 /* Need at least 1 byte in order to check version */
2787 if (status < (1)) {
2788 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002789 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2790 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002791 continue;
2792 }
jjako08d331d2003-10-13 20:33:30 +00002793
Harald Weltebed35df2011-11-02 13:06:18 +01002794 pheader = (struct gtp0_header *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002795
Harald Weltebed35df2011-11-02 13:06:18 +01002796 /* Version should be gtp0 (or earlier) */
2797 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2798 /* GTP 0 messages. If other version message is received we reply that we */
2799 /* only support version 0, implying that this is the only version */
2800 /* supported on this port */
Harald Weltefed598f2017-09-24 16:39:22 +08002801 if (GTPHDR_F_GET_VER(pheader->flags) > 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01002802 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002803 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2804 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002805 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2806 continue;
2807 }
2808
2809 /* Check length of gtp0 packet */
2810 if (status < GTP0_HEADER_SIZE) {
2811 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002812 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2813 status, "GTP0 packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002814 continue; /* Silently discard 29.60: 11.1.2 */
2815 }
2816
2817 /* Check packet length field versus length of packet */
2818 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2819 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002820 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002821 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002822 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002823 continue; /* Silently discard */
2824 }
2825
2826 if ((gsn->mode == GTP_MODE_GGSN) &&
2827 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2828 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2829 (pheader->type == GTP_DELETE_PDP_RSP))) {
2830 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002831 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002832 status,
Max28318872017-05-16 17:03:02 +02002833 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002834 continue; /* Silently discard 29.60: 11.1.4 */
2835 }
2836
2837 if ((gsn->mode == GTP_MODE_SGSN) &&
2838 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2839 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2840 (pheader->type == GTP_DELETE_PDP_REQ))) {
2841 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002842 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002843 status,
Max28318872017-05-16 17:03:02 +02002844 "Unexpected GTPv0 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002845 continue; /* Silently discard 29.60: 11.1.4 */
2846 }
2847
2848 switch (pheader->type) {
2849 case GTP_ECHO_REQ:
2850 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2851 break;
2852 case GTP_ECHO_RSP:
2853 gtp_echo_conf(gsn, version, &peer, buffer, status);
2854 break;
2855 case GTP_NOT_SUPPORTED:
2856 gtp_unsup_ind(gsn, &peer, buffer, status);
2857 break;
2858 case GTP_CREATE_PDP_REQ:
2859 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
2860 status);
2861 break;
2862 case GTP_CREATE_PDP_RSP:
2863 gtp_create_pdp_conf(gsn, version, &peer, buffer,
2864 status);
2865 break;
2866 case GTP_UPDATE_PDP_REQ:
2867 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
2868 status);
2869 break;
2870 case GTP_UPDATE_PDP_RSP:
2871 gtp_update_pdp_conf(gsn, version, &peer, buffer,
2872 status);
2873 break;
2874 case GTP_DELETE_PDP_REQ:
2875 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
2876 status);
2877 break;
2878 case GTP_DELETE_PDP_RSP:
2879 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
2880 status);
2881 break;
2882 case GTP_ERROR:
2883 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2884 break;
2885 case GTP_GPDU:
2886 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2887 break;
2888 default:
2889 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01002890 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
2891 "Unknown GTP message type received: %d\n",
2892 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01002893 break;
2894 }
2895 }
jjako08d331d2003-10-13 20:33:30 +00002896}
2897
jjako08d331d2003-10-13 20:33:30 +00002898int gtp_decaps1c(struct gsn_t *gsn)
2899{
Harald Weltebed35df2011-11-02 13:06:18 +01002900 unsigned char buffer[PACKET_MAX];
2901 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01002902 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01002903 int status;
2904 struct gtp1_header_short *pheader;
2905 int version = 1; /* TODO GTP version should be determined from header! */
2906 int fd = gsn->fd1c;
jjako08d331d2003-10-13 20:33:30 +00002907
Harald Weltebed35df2011-11-02 13:06:18 +01002908 /* TODO: Need strategy of userspace buffering and blocking */
2909 /* Currently read is non-blocking and send is blocking. */
2910 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00002911
Harald Weltebed35df2011-11-02 13:06:18 +01002912 while (1) { /* Loop until no more to read */
2913 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002914 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002915 return -1;
2916 }
2917 peerlen = sizeof(peer);
2918 if ((status =
2919 recvfrom(fd, buffer, sizeof(buffer), 0,
2920 (struct sockaddr *)&peer, &peerlen)) < 0) {
2921 if (errno == EAGAIN)
2922 return 0;
2923 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002924 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01002925 "recvfrom(fd=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01002926 fd, (unsigned long)buffer, sizeof(buffer),
2927 status, status ? strerror(errno) : "No error");
2928 return -1;
2929 }
jjako08d331d2003-10-13 20:33:30 +00002930
Harald Weltebed35df2011-11-02 13:06:18 +01002931 /* Need at least 1 byte in order to check version */
2932 if (status < (1)) {
2933 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002934 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2935 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002936 continue;
2937 }
jjako08d331d2003-10-13 20:33:30 +00002938
Harald Weltebed35df2011-11-02 13:06:18 +01002939 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00002940
Harald Weltebed35df2011-11-02 13:06:18 +01002941 /* Version must be no larger than GTP 1 */
Harald Weltefed598f2017-09-24 16:39:22 +08002942 if (GTPHDR_F_GET_VER(pheader->flags) > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01002943 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002944 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2945 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002946 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2947 /*29.60: 11.1.1 */
2948 continue;
2949 }
jjako08d331d2003-10-13 20:33:30 +00002950
Harald Weltebed35df2011-11-02 13:06:18 +01002951 /* Version must be at least GTP 1 */
2952 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2953 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2954 /* the message */
Harald Weltefed598f2017-09-24 16:39:22 +08002955 if (GTPHDR_F_GET_VER(pheader->flags) < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01002956 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002957 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2958 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002959 continue;
2960 }
jjako08d331d2003-10-13 20:33:30 +00002961
Harald Weltebed35df2011-11-02 13:06:18 +01002962 /* Check packet flag field */
2963 if (((pheader->flags & 0xf7) != 0x32)) {
2964 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002965 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01002966 status, "Unsupported packet flags: 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01002967 continue;
2968 }
jjako2c381332003-10-21 19:09:53 +00002969
Harald Weltebed35df2011-11-02 13:06:18 +01002970 /* Check length of packet */
2971 if (status < GTP1_HEADER_SIZE_LONG) {
2972 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002973 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2974 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002975 continue; /* Silently discard 29.60: 11.1.2 */
2976 }
jjako2c381332003-10-21 19:09:53 +00002977
Harald Weltebed35df2011-11-02 13:06:18 +01002978 /* Check packet length field versus length of packet */
2979 if (status !=
2980 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2981 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002982 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01002983 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002984 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002985 continue; /* Silently discard */
2986 }
jjako1db1c812003-07-06 20:53:57 +00002987
Harald Weltebed35df2011-11-02 13:06:18 +01002988 /* Check for extension headers */
2989 /* TODO: We really should cycle through the headers and determine */
2990 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08002991 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01002992 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01002993 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
2994 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01002995 gtp_extheader_req(gsn, version, &peer, fd, buffer,
2996 status);
jjako1db1c812003-07-06 20:53:57 +00002997
Harald Weltebed35df2011-11-02 13:06:18 +01002998 continue;
2999 }
3000
3001 if ((gsn->mode == GTP_MODE_GGSN) &&
3002 ((pheader->type == GTP_CREATE_PDP_RSP) ||
3003 (pheader->type == GTP_UPDATE_PDP_RSP) ||
3004 (pheader->type == GTP_DELETE_PDP_RSP))) {
3005 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003006 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003007 status,
Max28318872017-05-16 17:03:02 +02003008 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003009 continue; /* Silently discard 29.60: 11.1.4 */
3010 }
3011
3012 if ((gsn->mode == GTP_MODE_SGSN) &&
3013 ((pheader->type == GTP_CREATE_PDP_REQ) ||
3014 (pheader->type == GTP_UPDATE_PDP_REQ) ||
3015 (pheader->type == GTP_DELETE_PDP_REQ))) {
3016 gsn->unexpect++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003017 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003018 status,
Max28318872017-05-16 17:03:02 +02003019 "Unexpected GTPv1 Signalling Message\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003020 continue; /* Silently discard 29.60: 11.1.4 */
3021 }
3022
3023 switch (pheader->type) {
3024 case GTP_ECHO_REQ:
3025 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3026 break;
3027 case GTP_ECHO_RSP:
3028 gtp_echo_conf(gsn, version, &peer, buffer, status);
3029 break;
3030 case GTP_NOT_SUPPORTED:
3031 gtp_unsup_ind(gsn, &peer, buffer, status);
3032 break;
3033 case GTP_SUPP_EXT_HEADER:
3034 gtp_extheader_ind(gsn, &peer, buffer, status);
3035 break;
3036 case GTP_CREATE_PDP_REQ:
3037 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
3038 status);
3039 break;
3040 case GTP_CREATE_PDP_RSP:
3041 gtp_create_pdp_conf(gsn, version, &peer, buffer,
3042 status);
3043 break;
3044 case GTP_UPDATE_PDP_REQ:
3045 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
3046 status);
3047 break;
3048 case GTP_UPDATE_PDP_RSP:
3049 gtp_update_pdp_conf(gsn, version, &peer, buffer,
3050 status);
3051 break;
3052 case GTP_DELETE_PDP_REQ:
3053 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
3054 status);
3055 break;
3056 case GTP_DELETE_PDP_RSP:
3057 gtp_delete_pdp_conf(gsn, version, &peer, buffer,
3058 status);
3059 break;
3060 case GTP_ERROR:
3061 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3062 break;
3063 default:
3064 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003065 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3066 "Unknown GTP message type received: %u\n",
3067 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003068 break;
3069 }
3070 }
jjako52c24142002-12-16 13:33:51 +00003071}
3072
jjako08d331d2003-10-13 20:33:30 +00003073int gtp_decaps1u(struct gsn_t *gsn)
3074{
Harald Weltebed35df2011-11-02 13:06:18 +01003075 unsigned char buffer[PACKET_MAX];
3076 struct sockaddr_in peer;
Harald Welted88e11d2011-11-02 13:09:43 +01003077 socklen_t peerlen;
Harald Weltebed35df2011-11-02 13:06:18 +01003078 int status;
3079 struct gtp1_header_short *pheader;
3080 int version = 1; /* GTP version should be determined from header! */
3081 int fd = gsn->fd1u;
jjako08d331d2003-10-13 20:33:30 +00003082
Harald Weltebed35df2011-11-02 13:06:18 +01003083 /* TODO: Need strategy of userspace buffering and blocking */
3084 /* Currently read is non-blocking and send is blocking. */
3085 /* This means that the program have to wait for busy send calls... */
jjako08d331d2003-10-13 20:33:30 +00003086
Harald Weltebed35df2011-11-02 13:06:18 +01003087 while (1) { /* Loop until no more to read */
3088 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003089 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003090 return -1;
3091 }
3092 peerlen = sizeof(peer);
3093 if ((status =
3094 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
3095 (struct sockaddr *)&peer, &peerlen)) < 0) {
3096 if (errno == EAGAIN)
3097 return 0;
3098 gsn->err_readfrom++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003099 LOGP(DLGTP, LOGL_ERROR,
Alexander Huemerdb852a12015-11-06 20:59:01 +01003100 "recvfrom(fd1u=%d, buffer=%lx, len=%zu) failed: status = %d error = %s\n",
Harald Weltebed35df2011-11-02 13:06:18 +01003101 gsn->fd1u, (unsigned long)buffer,
3102 sizeof(buffer), status,
3103 status ? strerror(errno) : "No error");
3104 return -1;
3105 }
jjako08d331d2003-10-13 20:33:30 +00003106
Harald Weltebed35df2011-11-02 13:06:18 +01003107 /* Need at least 1 byte in order to check version */
3108 if (status < (1)) {
3109 gsn->empty++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003110 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3111 status, "Discarding packet - too small\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003112 continue;
3113 }
jjako08d331d2003-10-13 20:33:30 +00003114
Harald Weltebed35df2011-11-02 13:06:18 +01003115 pheader = (struct gtp1_header_short *)(buffer);
jjako08d331d2003-10-13 20:33:30 +00003116
Harald Weltebed35df2011-11-02 13:06:18 +01003117 /* Version must be no larger than GTP 1 */
Harald Weltefed598f2017-09-24 16:39:22 +08003118 if (GTPHDR_F_GET_VER(pheader->flags) > 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003119 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003120 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3121 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003122 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
3123 continue;
3124 }
jjako08d331d2003-10-13 20:33:30 +00003125
Harald Weltebed35df2011-11-02 13:06:18 +01003126 /* Version must be at least GTP 1 */
3127 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
3128 /* GTP 1 messages. If GTP 0 message is received we silently discard */
3129 /* the message */
Harald Weltefed598f2017-09-24 16:39:22 +08003130 if (GTPHDR_F_GET_VER(pheader->flags) < 1) {
Harald Weltebed35df2011-11-02 13:06:18 +01003131 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003132 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3133 status, "Unsupported GTP version\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003134 continue;
3135 }
jjako2c381332003-10-21 19:09:53 +00003136
Harald Weltebed35df2011-11-02 13:06:18 +01003137 /* Check packet flag field (allow both with and without sequence number) */
3138 if (((pheader->flags & 0xf5) != 0x30)) {
3139 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003140 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Welted37b80a2016-12-15 18:33:15 +01003141 status, "Unsupported packet flags 0x%02x\n", pheader->flags);
Harald Weltebed35df2011-11-02 13:06:18 +01003142 continue;
3143 }
jjako2c381332003-10-21 19:09:53 +00003144
Harald Weltebed35df2011-11-02 13:06:18 +01003145 /* Check length of packet */
3146 if (status < GTP1_HEADER_SIZE_SHORT) {
3147 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003148 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3149 status, "GTP packet too short\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003150 continue; /* Silently discard 29.60: 11.1.2 */
3151 }
3152
3153 /* Check packet length field versus length of packet */
3154 if (status !=
3155 (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
3156 gsn->tooshort++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003157 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
Harald Weltebed35df2011-11-02 13:06:18 +01003158 status,
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003159 "GTP packet length field does not match actual length\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003160 continue; /* Silently discard */
3161 }
3162
3163 /* Check for extension headers */
3164 /* TODO: We really should cycle through the headers and determine */
3165 /* if any have the comprehension required flag set */
Harald Weltefed598f2017-09-24 16:39:22 +08003166 if (((pheader->flags & GTP1HDR_F_EXT) != 0x00)) {
Harald Weltebed35df2011-11-02 13:06:18 +01003167 gsn->unsup++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003168 GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
3169 status, "Unsupported extension header\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003170 gtp_extheader_req(gsn, version, &peer, fd, buffer,
3171 status);
3172
3173 continue;
3174 }
3175
3176 switch (pheader->type) {
3177 case GTP_ECHO_REQ:
3178 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
3179 break;
3180 case GTP_ECHO_RSP:
3181 gtp_echo_conf(gsn, version, &peer, buffer, status);
3182 break;
3183 case GTP_SUPP_EXT_HEADER:
3184 gtp_extheader_ind(gsn, &peer, buffer, status);
3185 break;
3186 case GTP_ERROR:
3187 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
3188 break;
3189 /* Supported header extensions */
3190 case GTP_GPDU:
3191 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
3192 break;
3193 default:
3194 gsn->unknown++;
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003195 GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
3196 "Unknown GTP message type received: %u\n",
3197 pheader->type);
Harald Weltebed35df2011-11-02 13:06:18 +01003198 break;
3199 }
3200 }
jjako08d331d2003-10-13 20:33:30 +00003201}
3202
Harald Weltebed35df2011-11-02 13:06:18 +01003203int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +00003204{
Harald Weltebed35df2011-11-02 13:06:18 +01003205 union gtp_packet packet;
3206 struct sockaddr_in addr;
Harald Welte471e3492017-09-24 16:12:39 +08003207 struct msghdr msgh;
3208 struct iovec iov[2];
Harald Weltebed35df2011-11-02 13:06:18 +01003209 int fd;
jjako52c24142002-12-16 13:33:51 +00003210
Harald Welte471e3492017-09-24 16:12:39 +08003211 /* prepare destination address */
Harald Weltebed35df2011-11-02 13:06:18 +01003212 memset(&addr, 0, sizeof(addr));
3213 addr.sin_family = AF_INET;
jjako0fe0df02004-09-17 11:30:40 +00003214#if defined(__FreeBSD__) || defined(__APPLE__)
Harald Weltebed35df2011-11-02 13:06:18 +01003215 addr.sin_len = sizeof(addr);
jjako06e9f122004-01-19 18:37:58 +00003216#endif
Harald Weltebed35df2011-11-02 13:06:18 +01003217 memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00003218
Harald Welte471e3492017-09-24 16:12:39 +08003219 /* prepare msghdr */
3220 memset(&msgh, 0, sizeof(msgh));
3221 msgh.msg_name = &addr;
3222 msgh.msg_namelen = sizeof(addr);
3223 msgh.msg_iov = iov;
3224 msgh.msg_iovlen = ARRAY_SIZE(iov);
3225
3226 /* prepare iovectors */
3227 iov[0].iov_base = &packet;
3228 /* iov[0].iov_len is not known here yet */
3229 iov[1].iov_base = pack;
3230 iov[1].iov_len = len;
3231
Harald Weltebed35df2011-11-02 13:06:18 +01003232 if (pdp->version == 0) {
jjako52c24142002-12-16 13:33:51 +00003233
Harald Welte471e3492017-09-24 16:12:39 +08003234 iov[0].iov_len = GTP0_HEADER_SIZE;
Harald Weltebed35df2011-11-02 13:06:18 +01003235 addr.sin_port = htons(GTP0_PORT);
3236 fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00003237
Harald Weltebed35df2011-11-02 13:06:18 +01003238 get_default_gtp(0, GTP_GPDU, &packet);
3239 packet.gtp0.h.length = hton16(len);
Harald Welte3c1cce22017-09-24 16:40:12 +08003240 if (pdp->tx_gpdu_seq)
3241 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
3242 else
3243 packet.gtp0.h.seq = 0;
Harald Weltebed35df2011-11-02 13:06:18 +01003244 packet.gtp0.h.flow = hton16(pdp->flru);
Pablo Neira Ayuso746b9442014-03-24 17:58:27 +01003245 packet.gtp0.h.tid = htobe64(pdp_gettid(pdp->imsi, pdp->nsapi));
Harald Weltebed35df2011-11-02 13:06:18 +01003246 } else if (pdp->version == 1) {
jjako08d331d2003-10-13 20:33:30 +00003247
Harald Weltebed35df2011-11-02 13:06:18 +01003248 addr.sin_port = htons(GTP1U_PORT);
3249 fd = gsn->fd1u;
jjakoa7cd2492003-04-11 09:40:12 +00003250
Harald Weltebed35df2011-11-02 13:06:18 +01003251 get_default_gtp(1, GTP_GPDU, &packet);
Harald Welte3c1cce22017-09-24 16:40:12 +08003252 if (pdp->tx_gpdu_seq) {
3253 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
3254 packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
3255 GTP1_HEADER_SIZE_LONG);
3256 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
3257 iov[0].iov_len = GTP1_HEADER_SIZE_LONG;
3258 } else {
3259 packet.gtp1s.h.flags &= ~GTP1HDR_F_SEQ;
3260 packet.gtp1s.h.length = hton16(len);
3261 packet.gtp1s.h.tei = hton32(pdp->teid_gn);
3262 iov[0].iov_len = GTP1_HEADER_SIZE_SHORT;
3263 }
Harald Weltebed35df2011-11-02 13:06:18 +01003264 } else {
Holger Hans Peter Freyther01b40d02014-12-04 15:01:53 +01003265 LOGP(DLGTP, LOGL_ERROR, "Unknown version: %d\n", pdp->version);
Harald Weltebed35df2011-11-02 13:06:18 +01003266 return EOF;
3267 }
3268
3269 if (fcntl(fd, F_SETFL, 0)) {
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003270 LOGP(DLGTP, LOGL_ERROR, "fnctl()\n");
Harald Weltebed35df2011-11-02 13:06:18 +01003271 return -1;
3272 }
3273
Harald Welte471e3492017-09-24 16:12:39 +08003274 if (sendmsg(fd, &msgh, 0) < 0) {
Harald Weltebed35df2011-11-02 13:06:18 +01003275 gsn->err_sendto++;
Holger Hans Peter Freyther42ca1d12014-12-03 20:18:43 +01003276 LOGP(DLGTP, LOGL_ERROR,
Harald Welte471e3492017-09-24 16:12:39 +08003277 "sendmsg(fd=%d, msg=%lx, len=%d) failed: Error = %s\n", fd,
Harald Weltebed35df2011-11-02 13:06:18 +01003278 (unsigned long)&packet, GTP0_HEADER_SIZE + len,
3279 strerror(errno));
3280 return EOF;
3281 }
3282 return 0;
jjako52c24142002-12-16 13:33:51 +00003283}
3284
jjako52c24142002-12-16 13:33:51 +00003285/* ***********************************************************
3286 * Conversion functions
3287 *************************************************************/
3288
Harald Weltebed35df2011-11-02 13:06:18 +01003289int char2ul_t(char *src, struct ul_t dst)
3290{
3291 dst.l = strlen(src) + 1;
3292 dst.v = malloc(dst.l);
3293 dst.v[0] = dst.l - 1;
3294 memcpy(&dst.v[1], src, dst.v[0]);
3295 return 0;
jjako52c24142002-12-16 13:33:51 +00003296}
3297
3298/* ***********************************************************
3299 * IP address conversion functions
3300 * There exist several types of address representations:
3301 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3302 * Used for signalling address to mobile station. Supports IPv4
3303 * IPv6 x.25 etc. etc.
3304 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3305 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3306 * - in_addr: IPv4 address struct.
3307 * - sockaddr_in: Socket API representation of IP address and
3308 * port number.
3309 *************************************************************/
3310
Harald Weltebed35df2011-11-02 13:06:18 +01003311int ipv42eua(struct ul66_t *eua, struct in_addr *src)
3312{
Harald Weltecee75462017-09-24 17:45:05 +08003313 eua->v[0] = PDP_EUA_ORG_IETF;
3314 eua->v[1] = PDP_EUA_TYPE_v4;
Harald Weltebed35df2011-11-02 13:06:18 +01003315 if (src) {
3316 eua->l = 6;
3317 memcpy(&eua->v[2], src, 4);
3318 } else {
3319 eua->l = 2;
3320 }
3321 return 0;
jjako52c24142002-12-16 13:33:51 +00003322}
3323
Harald Weltebed35df2011-11-02 13:06:18 +01003324int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
3325{
Harald Weltecee75462017-09-24 17:45:05 +08003326 if ((eua->l != 6) || (eua->v[0] != PDP_EUA_ORG_IETF) || (eua->v[1] != PDP_EUA_TYPE_v4))
Harald Weltebed35df2011-11-02 13:06:18 +01003327 return -1; /* Not IPv4 address */
3328 memcpy(dst, &eua->v[2], 4);
3329 return 0;
jjako52c24142002-12-16 13:33:51 +00003330}
3331
Harald Weltebed35df2011-11-02 13:06:18 +01003332int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
3333{
3334 memset(dst, 0, sizeof(struct in_addr));
3335 if (gsna->l != 4)
3336 return EOF; /* Return if not IPv4 */
3337 memcpy(dst, gsna->v, gsna->l);
3338 return 0;
jjako52c24142002-12-16 13:33:51 +00003339}
3340
Harald Weltebed35df2011-11-02 13:06:18 +01003341int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
3342{
3343 memset(gsna, 0, sizeof(struct ul16_t));
3344 gsna->l = 4;
3345 memcpy(gsna->v, src, gsna->l);
3346 return 0;
jjako52c24142002-12-16 13:33:51 +00003347}
Harald Welteb10ee082017-08-12 19:29:16 +02003348
3349/* TS 29.060 has yet again a different encoding for IMSIs than
3350 * what we have in other places, so we cannot use the gsm48
3351 * decoding functions. Also, libgtp uses an uint64_t in
3352 * _network byte order_ to contain BCD digits ?!? */
3353const char *imsi_gtp2str(const uint64_t *imsi)
3354{
Harald Weltea06120d2017-11-06 03:12:54 +09003355 static char buf[sizeof(*imsi)*2+1];
Harald Welteb10ee082017-08-12 19:29:16 +02003356 const uint8_t *imsi8 = (const uint8_t *) imsi;
3357 unsigned int i, j = 0;
3358
3359 for (i = 0; i < sizeof(*imsi); i++) {
3360 uint8_t nibble;
3361
3362 nibble = imsi8[i] & 0xf;
3363 if (nibble == 0xf)
3364 break;
3365 buf[j++] = osmo_bcd2char(nibble);
3366
3367 nibble = imsi8[i] >> 4;
3368 if (nibble == 0xf)
3369 break;
3370 buf[j++] = osmo_bcd2char(nibble);
3371 }
3372
3373 buf[j++] = '\0';
3374 return buf;
3375}