blob: 6f94aa50dabc31f918f58dbf07e7959e9e36552b [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002 Mondru AB.
4 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
10 * The initial developer of the original code is
11 * Jens Jakobsen <jj@openggsn.org>
12 *
13 * Contributor(s):
14 *
15 */
16
17/*
18 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
19 * tunnels in the same program.
20 *
21 * TODO:
22 * - Do we need to handle fragmentation?
23 */
24
25
26#ifdef __linux__
27#define _GNU_SOURCE 1
28#endif
29
30
31#include <syslog.h>
32#include <stdio.h>
33#include <stdarg.h>
34#include <stdlib.h>
35#include <sys/time.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#include <sys/stat.h>
41#include <time.h>
42#include <unistd.h>
43#include <string.h>
44#include <errno.h>
45#include <fcntl.h>
46
47#include <arpa/inet.h>
48
49#include <stdint.h> /* ISO C99 types */
50
jjako3c13e302003-01-28 22:17:29 +000051#include "../config.h"
jjako52c24142002-12-16 13:33:51 +000052#include "pdp.h"
53#include "gtp.h"
54#include "gtpie.h"
55#include "queue.h"
56
jjako1db1c812003-07-06 20:53:57 +000057
58/* Error reporting functions */
59
60void gtp_err(int priority, char *filename, int linenum, char *fmt, ...) {
61 va_list args;
62 char buf[ERRMSG_SIZE];
63
64 va_start(args, fmt);
65 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
66 va_end(args);
67 buf[ERRMSG_SIZE-1] = 0;
68 syslog(priority, "%s: %d: %s", filename, linenum, buf);
69}
70
71void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
72 void *pack, unsigned len, char *fmt, ...) {
73
74 va_list args;
75 char buf[ERRMSG_SIZE];
76 char buf2[ERRMSG_SIZE];
77 int n;
78 int pos;
79
80 va_start(args, fmt);
81 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
82 va_end(args);
83 buf[ERRMSG_SIZE-1] = 0;
84
85 snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
86 inet_ntoa(peer->sin_addr),
87 ntohs(peer->sin_port),
88 len);
89 buf2[ERRMSG_SIZE-1] = 0;
90 pos = strlen(buf2);
91 for(n=0; n<len; n++) {
92 if ((pos+4)<ERRMSG_SIZE) {
93 sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
94 pos += 3;
95 }
96 }
97 buf2[pos] = 0;
98
99 syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
100
101}
102
103
104
105
jjako52c24142002-12-16 13:33:51 +0000106/* API Functions */
107
108const char* gtp_version()
109{
110 return VERSION;
111}
112
113/* gtp_new */
114/* gtp_free */
115
116int gtp_newpdp(struct gsn_t* gsn, struct pdp_t **pdp,
117 uint64_t imsi, uint8_t nsapi) {
118 return pdp_newpdp(pdp, imsi, nsapi, NULL);
119}
120
121int gtp_freepdp(struct gsn_t* gsn, struct pdp_t *pdp) {
122 return pdp_freepdp(pdp);
123}
124
jjako52c24142002-12-16 13:33:51 +0000125/* gtp_gpdu */
126
127extern int gtp_fd(struct gsn_t *gsn) {
jjako08d331d2003-10-13 20:33:30 +0000128 return gsn->fd0;
jjako52c24142002-12-16 13:33:51 +0000129}
130
131/* gtp_decaps */
132/* gtp_retrans */
133/* gtp_retranstimeout */
134
jjako08d331d2003-10-13 20:33:30 +0000135
136int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
137 int (*cb) (struct sockaddr_in *peer)) {
138 gsn->cb_unsup_ind = cb;
139 return 0;
140}
141
jjako2c381332003-10-21 19:09:53 +0000142int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
143 int (*cb) (struct sockaddr_in *peer)) {
144 gsn->cb_extheader_ind = cb;
145 return 0;
146}
147
jjako08d331d2003-10-13 20:33:30 +0000148
149/* API: Initialise delete context callback */
150/* Called whenever a pdp context is deleted for any reason */
jjako52c24142002-12-16 13:33:51 +0000151int gtp_set_cb_delete_context(struct gsn_t *gsn,
jjako08d331d2003-10-13 20:33:30 +0000152 int (*cb) (struct pdp_t* pdp))
jjako52c24142002-12-16 13:33:51 +0000153{
jjako08d331d2003-10-13 20:33:30 +0000154 gsn->cb_delete_context = cb;
jjako52c24142002-12-16 13:33:51 +0000155 return 0;
156}
157
jjako52c24142002-12-16 13:33:51 +0000158int gtp_set_cb_conf(struct gsn_t *gsn,
159 int (*cb) (int type, int cause,
jjako08d331d2003-10-13 20:33:30 +0000160 struct pdp_t* pdp, void *cbp)) {
jjako52c24142002-12-16 13:33:51 +0000161 gsn->cb_conf = cb;
162 return 0;
163}
164
jjako08d331d2003-10-13 20:33:30 +0000165extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
166 int (*cb_data_ind) (struct pdp_t* pdp,
jjako52c24142002-12-16 13:33:51 +0000167 void* pack,
168 unsigned len))
169{
jjako08d331d2003-10-13 20:33:30 +0000170 gsn->cb_data_ind = cb_data_ind;
jjako52c24142002-12-16 13:33:51 +0000171 return 0;
172}
173
jjako08d331d2003-10-13 20:33:30 +0000174/**
175 * get_default_gtp()
176 * Generate a GPRS Tunneling Protocol signalling packet header, depending
177 * on GTP version and message type. pdp is used for teid/flow label.
178 * *packet must be allocated by the calling function, and be large enough
179 * to hold the packet header.
180 * returns the length of the header. 0 on error.
181 **/
182static int get_default_gtp(int version, u_int8_t type, void *packet) {
jjakoa7cd2492003-04-11 09:40:12 +0000183 struct gtp0_header *gtp0_default = (struct gtp0_header*) packet;
184 struct gtp1_header_long *gtp1_default = (struct gtp1_header_long*) packet;
jjako52c24142002-12-16 13:33:51 +0000185 switch (version) {
186 case 0:
jjakoa7cd2492003-04-11 09:40:12 +0000187 /* Initialise "standard" GTP0 header */
jjako08d331d2003-10-13 20:33:30 +0000188 memset(gtp0_default, 0, sizeof(struct gtp0_header));
jjakoa7cd2492003-04-11 09:40:12 +0000189 gtp0_default->flags=0x1e;
jjako08d331d2003-10-13 20:33:30 +0000190 gtp0_default->type=hton8(type);
jjakoa7cd2492003-04-11 09:40:12 +0000191 gtp0_default->spare1=0xff;
192 gtp0_default->spare2=0xff;
193 gtp0_default->spare3=0xff;
194 gtp0_default->number=0xff;
jjako08d331d2003-10-13 20:33:30 +0000195 return GTP0_HEADER_SIZE;
jjako52c24142002-12-16 13:33:51 +0000196 case 1:
jjakoa7cd2492003-04-11 09:40:12 +0000197 /* Initialise "standard" GTP1 header */
jjako08d331d2003-10-13 20:33:30 +0000198 /* 29.060: 8.2: S=1 and PN=0 */
199 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
200 /* and Supported Extension Headers Notification, the S field shall be */
201 /* set to 1 */
202 /* Currently extension headers are not supported */
203 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
204 gtp1_default->flags=0x32; /* No extension, enable sequence, no N-PDU */
205 gtp1_default->type=hton8(type);
206 return GTP1_HEADER_SIZE_LONG;
207 default:
208 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown GTP packet version");
209 return 0;
jjako52c24142002-12-16 13:33:51 +0000210 }
211}
212
jjako08d331d2003-10-13 20:33:30 +0000213/**
214 * get_seq()
215 * Get sequence number of a packet.
216 * Returns 0 on error
217 **/
218static uint16_t get_seq(void *pack) {
219 union gtp_packet *packet = (union gtp_packet *) pack;
220
221 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
222 return ntoh16(packet->gtp0.h.seq);
223 }
224 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
225 return ntoh16(packet->gtp1l.h.seq);
226 } else {
227 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
228 return 0;
229 }
230}
231
232/**
233 * get_tid()
234 * Get tunnel identifier of a packet.
235 * Returns 0 on error
236 **/
237static uint64_t get_tid(void *pack) {
238 union gtp_packet *packet = (union gtp_packet *) pack;
239
240 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
241 return packet->gtp0.h.tid;
242 }
243 return 0;
244}
245
246/**
247 * get_hlen()
248 * Get the header length of a packet.
249 * Returns 0 on error
250 **/
251static uint16_t get_hlen(void *pack) {
252 union gtp_packet *packet = (union gtp_packet *) pack;
253
254 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
255 return GTP0_HEADER_SIZE;
256 }
257 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
258 return GTP1_HEADER_SIZE_LONG;
259 }
260 else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
261 return GTP1_HEADER_SIZE_SHORT;
262 } else {
263 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
264 return 0;
265 }
266}
267
268/**
269 * get_tei()
270 * Get the tunnel endpoint identifier (flow label) of a packet.
271 * Returns 0xffffffff on error.
272 **/
273static uint32_t get_tei(void *pack) {
274 union gtp_packet *packet = (union gtp_packet *) pack;
275
276 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
277 return ntoh16(packet->gtp0.h.flow);
278 }
279 else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
280 return ntoh32(packet->gtp1l.h.tei);
281 }
282 else {
283 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
284 return 0xffffffff;
285 }
286}
jjakoa7cd2492003-04-11 09:40:12 +0000287
288
jjako52c24142002-12-16 13:33:51 +0000289int print_packet(void *packet, unsigned len)
290{
291 int i;
292 printf("The packet looks like this (%d bytes):\n", len);
293 for( i=0; i<len; i++) {
294 printf("%02x ", (unsigned char)*(char *)(packet+i));
295 if (!((i+1)%16)) printf("\n");
296 };
297 printf("\n");
298 return 0;
299}
300
301char* snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
302 void *pack, unsigned len, char *buf, int size) {
303 int n;
304 int pos;
305 snprintf(buf, size, "Packet from %s:%u, length: %d, content:",
306 inet_ntoa(peer->sin_addr),
307 ntohs(peer->sin_port),
308 len);
jjako2e840a32003-01-28 16:05:18 +0000309 buf[size-1] = 0;
jjako52c24142002-12-16 13:33:51 +0000310 pos = strlen(buf);
311 for(n=0; n<len; n++) {
312 if ((pos+4)<size) {
313 sprintf((buf+pos), " %02hhx", ((unsigned char*)pack)[n]);
314 pos += 3;
315 }
316 }
317 buf[pos] = 0;
318 return buf;
319}
320
jjako52c24142002-12-16 13:33:51 +0000321
322/* ***********************************************************
323 * Reliable delivery of signalling messages
324 *
325 * Sequence numbers are used for both signalling messages and
326 * data messages.
327 *
328 * For data messages each tunnel maintains a sequence counter,
329 * which is incremented by one each time a new data message
330 * is sent. The sequence number starts at (0) zero at tunnel
331 * establishment, and wraps around at 65535 (29.060 9.3.1.1
332 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
333 * or can be used to check the validity of the message in the
334 * receiver, or for reordering af packets.
335 *
336 * For signalling messages the sequence number is used by
337 * signalling messages for which a response is defined. A response
338 * message should copy the sequence from the corresponding request
339 * message. The sequence number "unambiguously" identifies a request
340 * message within a given path, with a path being defined as a set of
341 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
342 * messages shall be responded to, and all response messages associated
343 * with a certain request shall always include the same information"
344 *
345 * We take this to mean that the GSN transmitting a request is free to
346 * choose the sequence number, as long as it is unique within a given path.
347 * It means that we are allowed to count backwards, or roll over at 17
348 * if we prefer that. It also means that we can use the same counter for
349 * all paths. This has the advantage that the transmitted request sequence
350 * numbers are unique within each GSN, and also we dont have to mess around
351 * with path setup and teardown.
352 *
353 * If a response message is lost, the request will be retransmitted, and
354 * the receiving GSN will receive a "duplicated" request. The standard
355 * requires the receiving GSN to send a response, with the same information
356 * as in the original response. For most messages this happens automatically:
357 *
358 * Echo: Automatically dublicates the original response
359 * Create pdp context: The SGSN may send create context request even if
360 * a context allready exist (imsi+nsapi?). This means that the reply will
361 automatically dublicate the original response. It might however have
jjako08d331d2003-10-13 20:33:30 +0000362 * side effects in the application which is asked twice to validate
363 * the login.
jjako52c24142002-12-16 13:33:51 +0000364 * Update pdp context: Automatically dublicates the original response???
365 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
366 * a nonexist reply message.
367 *
368 * The correct solution will be to make a queue containing response messages.
369 * This queue should be checked whenever a request is received. If the
370 * response is allready in the queue that response should be transmitted.
371 * It should be possible to find messages in this queue on the basis of
372 * the sequence number and peer GSN IP address (The sequense number is unique
373 * within each path). This need to be implemented by a hash table. Furthermore
374 * it should be possibly to delete messages based on a timeout. This can be
375 * achieved by means of a linked list. The timeout value need to be larger
376 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
377 * set in the peer GSN, so there is no way to know these parameters. On the
378 * other hand the timeout value need to be so small that we do not receive
379 * wraparound sequence numbere before the message is deleted. 60 seconds is
380 * probably not a bad choise.
381 *
382 * This queue however is first really needed from gtp1.
383 *
384 * gtp_req:
385 * Send off a signalling message with appropiate sequence
386 * number. Store packet in queue.
387 * gtp_conf:
388 * Remove an incoming confirmation from the queue
389 * gtp_resp:
jjako08d331d2003-10-13 20:33:30 +0000390 * Send off a response to a request. Use the same sequence
jjako52c24142002-12-16 13:33:51 +0000391 * number in the response as in the request.
jjako2c381332003-10-21 19:09:53 +0000392 * gtp_notification:
393 * Send off a notification message. This is neither a request nor
394 * a response. Both TEI and SEQ are zero.
jjako52c24142002-12-16 13:33:51 +0000395 * gtp_retrans:
396 * Retransmit any outstanding packets which have exceeded
397 * a predefined timeout.
398 *************************************************************/
399
jjako08d331d2003-10-13 20:33:30 +0000400int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
401 union gtp_packet *packet, int len,
402 struct in_addr *inetaddr, void *cbp) {
jjako52c24142002-12-16 13:33:51 +0000403 struct sockaddr_in addr;
404 struct qmsg_t *qmsg;
jjako08d331d2003-10-13 20:33:30 +0000405 int fd;
406
jjako52c24142002-12-16 13:33:51 +0000407 memset(&addr, 0, sizeof(addr));
408 addr.sin_family = AF_INET;
409 addr.sin_addr = *inetaddr;
jjako52c24142002-12-16 13:33:51 +0000410
jjako08d331d2003-10-13 20:33:30 +0000411 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
412 addr.sin_port = htons(GTP0_PORT);
413 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
414 packet->gtp0.h.seq = hton16(gsn->seq_next);
415 if (pdp)
416 packet->gtp0.h.tid = (pdp->imsi & 0x0fffffffffffffff) +
417 ((uint64_t)pdp->nsapi << 60);
418 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
419 (packet->gtp0.h.type == GTP_ERROR)))
420 packet->gtp0.h.flow=hton16(pdp->flru);
421 else if (pdp)
422 packet->gtp0.h.flow=hton16(pdp->flrc);
423 fd = gsn->fd0;
424 }
425 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
426 addr.sin_port = htons(GTP1C_PORT);
427 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
428 packet->gtp1l.h.seq = hton16(gsn->seq_next);
429 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
430 (packet->gtp1l.h.type == GTP_ERROR)))
431 packet->gtp1l.h.tei=hton32(pdp->teid_gn);
432 else if (pdp)
433 packet->gtp1l.h.tei=hton32(pdp->teic_gn);
434 fd = gsn->fd1c;
435 } else {
436 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
437 return -1;
438 }
jjako52c24142002-12-16 13:33:51 +0000439
jjako08d331d2003-10-13 20:33:30 +0000440 if (sendto(fd, packet, len, 0,
jjako52c24142002-12-16 13:33:51 +0000441 (struct sockaddr *) &addr, sizeof(addr)) < 0) {
442 gsn->err_sendto++;
jjako08d331d2003-10-13 20:33:30 +0000443 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
jjako52c24142002-12-16 13:33:51 +0000444 return -1;
445 }
446
447 /* Use new queue structure */
448 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
449 gsn->err_queuefull++;
450 gtp_err(LOG_ERR, __FILE__, __LINE__, "Retransmit queue is full");
451 }
452 else {
453 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
454 qmsg->l = len;
455 qmsg->timeout = time(NULL) + 3; /* When to timeout */
456 qmsg->retrans = 0; /* No retransmissions so far */
jjako08d331d2003-10-13 20:33:30 +0000457 qmsg->cbp = cbp;
jjako52c24142002-12-16 13:33:51 +0000458 qmsg->type = ntoh8(packet->gtp0.h.type);
jjako08d331d2003-10-13 20:33:30 +0000459 qmsg->fd = fd;
jjako52c24142002-12-16 13:33:51 +0000460 }
461 gsn->seq_next++; /* Count up this time */
462 return 0;
463}
464
465/* gtp_conf
466 * Remove signalling packet from retransmission queue.
467 * return 0 on success, EOF if packet was not found */
468
469int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
jjako08d331d2003-10-13 20:33:30 +0000470 union gtp_packet *packet, int len, uint8_t *type, void **cbp) {
jjako52c24142002-12-16 13:33:51 +0000471
jjako08d331d2003-10-13 20:33:30 +0000472 uint16_t seq;
473
474 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
475 seq = ntoh16(packet->gtp0.h.seq);
476 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
477 seq = ntoh16(packet->gtp1l.h.seq);
478 else {
479 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
480 "Unknown GTP packet version");
481 return EOF;
482 }
483
484 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
jjako52c24142002-12-16 13:33:51 +0000485 gsn->err_seq++;
486 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
487 "Confirmation packet not found in queue");
488 return EOF;
489 }
490
491 return 0;
492}
493
494int gtp_retrans(struct gsn_t *gsn) {
495 /* Retransmit any outstanding packets */
496 /* Remove from queue if maxretrans exceeded */
497 time_t now;
498 struct qmsg_t *qmsg;
499 now = time(NULL);
500 /*printf("Retrans: New beginning %d\n", (int) now);*/
501
502 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
503 (qmsg->timeout <= now)) {
504 /*printf("Retrans timeout found: %d\n", (int) time(NULL));*/
505 if (qmsg->retrans > 3) { /* To many retrans */
jjako08d331d2003-10-13 20:33:30 +0000506 if (gsn->cb_conf) gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
jjako52c24142002-12-16 13:33:51 +0000507 queue_freemsg(gsn->queue_req, qmsg);
508 }
509 else {
jjako08d331d2003-10-13 20:33:30 +0000510 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
jjako52c24142002-12-16 13:33:51 +0000511 (struct sockaddr *) &qmsg->peer, sizeof(struct sockaddr_in)) < 0) {
512 gsn->err_sendto++;
jjako08d331d2003-10-13 20:33:30 +0000513 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s", gsn->fd0, (unsigned long) &qmsg->p, qmsg->l, strerror(errno));
jjako52c24142002-12-16 13:33:51 +0000514 }
515 queue_back(gsn->queue_req, qmsg);
516 qmsg->timeout = now + 3;
517 qmsg->retrans++;
518 }
519 }
520
521 /* Also clean up reply timeouts */
522 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
523 (qmsg->timeout < now)) {
524 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL));*/
525 queue_freemsg(gsn->queue_resp, qmsg);
526 }
527
528 return 0;
529}
530
531int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout) {
532 time_t now, later;
533 struct qmsg_t *qmsg;
534
535 if (queue_getfirst(gsn->queue_req, &qmsg)) {
536 timeout->tv_sec = 10;
537 timeout->tv_usec = 0;
538 }
539 else {
540 now = time(NULL);
541 later = qmsg->timeout;
542 timeout->tv_sec = later - now;
543 timeout->tv_usec = 0;
544 if (timeout->tv_sec < 0) timeout->tv_sec = 0; /* No negative allowed */
545 if (timeout->tv_sec > 10) timeout->tv_sec = 10; /* Max sleep for 10 sec*/
546 }
547 return 0;
548}
549
jjako08d331d2003-10-13 20:33:30 +0000550int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
551 union gtp_packet *packet, int len,
552 struct sockaddr_in *peer, int fd,
553 uint16_t seq, uint64_t tid) {
jjako52c24142002-12-16 13:33:51 +0000554 struct qmsg_t *qmsg;
jjako52c24142002-12-16 13:33:51 +0000555
jjako08d331d2003-10-13 20:33:30 +0000556 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
557 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
558 packet->gtp0.h.seq = hton16(seq);
559 packet->gtp0.h.tid = tid;
560 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
561 (packet->gtp0.h.type == GTP_ERROR)))
562 packet->gtp0.h.flow=hton16(pdp->flru);
563 else if (pdp)
564 packet->gtp0.h.flow=hton16(pdp->flrc);
565 }
566 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
567 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
568 packet->gtp1l.h.seq = hton16(seq);
569 if (pdp && (fd == gsn->fd1u))
570 packet->gtp1l.h.tei=hton32(pdp->teid_gn);
571 else if (pdp)
572 packet->gtp1l.h.tei=hton32(pdp->teic_gn);
573 }
574 else {
575 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
jjakoa7cd2492003-04-11 09:40:12 +0000576 return -1;
577 }
jjako52c24142002-12-16 13:33:51 +0000578
jjako08d331d2003-10-13 20:33:30 +0000579 if (fcntl(fd, F_SETFL, 0)) {
580 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
581 return -1;
582 }
583
584 if (sendto(fd, packet, len, 0,
jjako52c24142002-12-16 13:33:51 +0000585 (struct sockaddr *) peer, sizeof(struct sockaddr_in)) < 0) {
586 gsn->err_sendto++;
jjako08d331d2003-10-13 20:33:30 +0000587 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
jjako52c24142002-12-16 13:33:51 +0000588 return -1;
589 }
590
591 /* Use new queue structure */
592 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
593 gsn->err_queuefull++;
594 gtp_err(LOG_ERR, __FILE__, __LINE__, "Retransmit queue is full");
595 }
596 else {
597 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
598 qmsg->l = len;
599 qmsg->timeout = time(NULL) + 60; /* When to timeout */
600 qmsg->retrans = 0; /* No retransmissions so far */
jjako08d331d2003-10-13 20:33:30 +0000601 qmsg->cbp = NULL;
jjako52c24142002-12-16 13:33:51 +0000602 qmsg->type = 0;
jjako08d331d2003-10-13 20:33:30 +0000603 qmsg->fd = fd;
jjako52c24142002-12-16 13:33:51 +0000604 }
605 return 0;
606}
607
jjako2c381332003-10-21 19:09:53 +0000608int gtp_notification(struct gsn_t *gsn, int version,
609 union gtp_packet *packet, int len,
610 struct sockaddr_in *peer, int fd,
611 uint16_t seq) {
612
613 struct sockaddr_in addr;
614
615 memcpy(&addr, peer, sizeof(addr));
616
617 /* In GTP0 notifications are treated as replies. In GTP1 they
618 are requests for which there is no reply */
619
620 if (fd == gsn->fd1c)
621 addr.sin_port = htons(GTP1C_PORT);
622 else if (fd == gsn->fd1u)
623 addr.sin_port = htons(GTP1C_PORT);
624
625 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
626 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
627 packet->gtp0.h.seq = hton16(seq);
628 }
629 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
630 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
631 packet->gtp1l.h.seq = hton16(seq);
632 }
633 else {
634 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
635 return -1;
636 }
637
638 if (fcntl(fd, F_SETFL, 0)) {
639 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
640 return -1;
641 }
642
643 if (sendto(fd, packet, len, 0,
644 (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) {
645 gsn->err_sendto++;
646 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
647 return -1;
648 }
649 return 0;
650}
651
jjako52c24142002-12-16 13:33:51 +0000652int gtp_dublicate(struct gsn_t *gsn, int version,
653 struct sockaddr_in *peer, uint16_t seq) {
654 struct qmsg_t *qmsg;
655
656 if(queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
657 return EOF; /* Notfound */
658 }
jjakoa7cd2492003-04-11 09:40:12 +0000659
jjako08d331d2003-10-13 20:33:30 +0000660 if (fcntl(qmsg->fd, F_SETFL, 0)) {
661 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
662 return -1;
jjako52c24142002-12-16 13:33:51 +0000663 }
jjako08d331d2003-10-13 20:33:30 +0000664
665 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
666 (struct sockaddr *) peer, sizeof(struct sockaddr_in)) < 0) {
667 gsn->err_sendto++;
668 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", qmsg->fd, (unsigned long) &qmsg->p, qmsg->l, strerror(errno));
669 }
670 return 0;
jjako52c24142002-12-16 13:33:51 +0000671}
672
673
674
675/* Perform restoration and recovery error handling as described in 29.060 */
676static void log_restart(struct gsn_t *gsn) {
677 FILE *f;
678 int i;
679 int counter = 0;
680 char filename[NAMESIZE];
681
682 filename[NAMESIZE-1] = 0; /* No null term. guarantee by strncpy */
683 strncpy(filename, gsn->statedir, NAMESIZE-1);
684 strncat(filename, RESTART_FILE,
685 NAMESIZE-1-sizeof(RESTART_FILE));
686
687 i = umask(022);
688
689 /* We try to open file. On failure we will later try to create file */
690 if (!(f = fopen(filename, "r"))) {
691 gtp_err(LOG_ERR, __FILE__, __LINE__, "fopen(path=%s, mode=%s) failed: Error = %s", filename, "r", strerror(errno));
692 }
693 else {
694 umask(i);
695 fscanf(f, "%d", &counter);
696 if (fclose(f)) {
697 gtp_err(LOG_ERR, __FILE__, __LINE__, "fclose failed: Error = %s", strerror(errno));
698 }
699 }
700
701 gsn->restart_counter = (unsigned char) counter;
702 gsn->restart_counter++;
703
704 if (!(f = fopen(filename, "w"))) {
705 gtp_err(LOG_ERR, __FILE__, __LINE__, "fopen(path=%s, mode=%s) failed: Error = %s", filename, "w", strerror(errno));
706 return;
707 }
708
709 umask(i);
710 fprintf(f, "%d\n", gsn->restart_counter);
711 if (fclose(f)) {
712 gtp_err(LOG_ERR, __FILE__, __LINE__, "fclose failed: Error = %s", strerror(errno));
713 return;
714 }
715}
716
717
718
jjako1db1c812003-07-06 20:53:57 +0000719int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
720 int mode)
jjako52c24142002-12-16 13:33:51 +0000721{
722 struct sockaddr_in addr;
jjako52c24142002-12-16 13:33:51 +0000723
724 syslog(LOG_ERR, "GTP: gtp_newgsn() started");
725
726 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
727
728 (*gsn)->statedir = statedir;
729 log_restart(*gsn);
jjakoa7cd2492003-04-11 09:40:12 +0000730
731 /* Initialise sequence number */
732 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
jjako52c24142002-12-16 13:33:51 +0000733
734 /* Initialise request retransmit queue */
735 queue_new(&(*gsn)->queue_req);
736 queue_new(&(*gsn)->queue_resp);
737
738 /* Initialise pdp table */
739 pdp_init();
740
741 /* Initialise call back functions */
jjako08d331d2003-10-13 20:33:30 +0000742 (*gsn)->cb_create_context_ind = 0;
jjako52c24142002-12-16 13:33:51 +0000743 (*gsn)->cb_delete_context = 0;
jjako08d331d2003-10-13 20:33:30 +0000744 (*gsn)->cb_unsup_ind = 0;
jjako52c24142002-12-16 13:33:51 +0000745 (*gsn)->cb_conf = 0;
jjako08d331d2003-10-13 20:33:30 +0000746 (*gsn)->cb_data_ind = 0;
jjako52c24142002-12-16 13:33:51 +0000747
jjako08d331d2003-10-13 20:33:30 +0000748 /* Store function parameters */
749 (*gsn)->gsnc = *listen;
750 (*gsn)->gsnu = *listen;
751 (*gsn)->mode = mode;
752
753
754 /* Create GTP version 0 socket */
755 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
jjako52c24142002-12-16 13:33:51 +0000756 (*gsn)->err_socket++;
757 gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
758 return -1;
759 }
jjako52c24142002-12-16 13:33:51 +0000760
761 memset(&addr, 0, sizeof(addr));
jjako52c24142002-12-16 13:33:51 +0000762 addr.sin_family = AF_INET;
jjako52c24142002-12-16 13:33:51 +0000763 addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
764 addr.sin_port = htons(GTP0_PORT);
765
jjako08d331d2003-10-13 20:33:30 +0000766 if (bind((*gsn)->fd0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
jjako52c24142002-12-16 13:33:51 +0000767 (*gsn)->err_socket++;
jjako08d331d2003-10-13 20:33:30 +0000768 gtp_err(LOG_ERR, __FILE__, __LINE__, "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s", (*gsn)->fd0, (unsigned long) &addr, sizeof(addr), strerror(errno));
769 return -1;
770 }
771
772 /* Create GTP version 1 control plane socket */
773 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
774 (*gsn)->err_socket++;
775 gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
776 return -1;
777 }
778
779 memset(&addr, 0, sizeof(addr));
780 addr.sin_family = AF_INET;
781 addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
782 addr.sin_port = htons(GTP1C_PORT);
783
784 if (bind((*gsn)->fd1c, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
785 (*gsn)->err_socket++;
786 gtp_err(LOG_ERR, __FILE__, __LINE__, "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s", (*gsn)->fd1c, (unsigned long) &addr, sizeof(addr), strerror(errno));
787 return -1;
788 }
789
790 /* Create GTP version 1 user plane socket */
791 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
792 (*gsn)->err_socket++;
793 gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
794 return -1;
795 }
796
797 memset(&addr, 0, sizeof(addr));
798 addr.sin_family = AF_INET;
799 addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
800 addr.sin_port = htons(GTP1U_PORT);
801
802 if (bind((*gsn)->fd1u, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
803 (*gsn)->err_socket++;
804 gtp_err(LOG_ERR, __FILE__, __LINE__, "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s", (*gsn)->fd1c, (unsigned long) &addr, sizeof(addr), strerror(errno));
jjako52c24142002-12-16 13:33:51 +0000805 return -1;
806 }
807
jjako52c24142002-12-16 13:33:51 +0000808 return 0;
809}
810
811int gtp_free(struct gsn_t *gsn) {
812
813 /* Clean up retransmit queues */
814 queue_free(gsn->queue_req);
815 queue_free(gsn->queue_resp);
jjako08d331d2003-10-13 20:33:30 +0000816
817 close(gsn->fd0);
818 close(gsn->fd1c);
819 close(gsn->fd1u);
jjako52c24142002-12-16 13:33:51 +0000820
821 free(gsn);
822 return 0;
823}
824
825/* ***********************************************************
826 * Path management messages
827 * Messages: echo and version not supported.
828 * A path is connection between two UDP/IP endpoints
829 *
830 * A path is either using GTP0 or GTP1. A path can be
831 * established by any kind of GTP message??
832
833 * Which source port to use?
834 * GTP-C request destination port is 2123/3386
835 * GTP-U request destination port is 2152/3386
836 * T-PDU destination port is 2152/3386.
837 * For the above messages the source port is locally allocated.
838 * For response messages src=rx-dst and dst=rx-src.
839 * For simplicity we should probably use 2123+2152/3386 as
840 * src port even for the cases where src can be locally
841 * allocated. This also means that we have to listen only to
842 * the same ports.
843 * For response messages we need to be able to respond to
844 * the relevant src port even if it is locally allocated by
845 * the peer.
846 *
847 * The need for path management!
848 * We might need to keep a list of active paths. This might
849 * be in the form of remote IP address + UDP port numbers.
850 * (We will consider a path astablished if we have a context
851 * with the node in question)
852 *************************************************************/
853
854/* Send off an echo request */
jjako08d331d2003-10-13 20:33:30 +0000855int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
856 struct in_addr *inetaddr)
jjako52c24142002-12-16 13:33:51 +0000857{
858 union gtp_packet packet;
jjako08d331d2003-10-13 20:33:30 +0000859 int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
860 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +0000861}
862
jjako08d331d2003-10-13 20:33:30 +0000863/* Send off an echo reply */
864int gtp_echo_resp(struct gsn_t *gsn, int version,
865 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +0000866 void *pack, unsigned len)
867{
868 union gtp_packet packet;
jjako08d331d2003-10-13 20:33:30 +0000869 int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
870 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY, gsn->restart_counter);
871 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
872 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +0000873}
874
875
876/* Handle a received echo request */
jjako08d331d2003-10-13 20:33:30 +0000877int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
878 int fd, void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +0000879
jjako08d331d2003-10-13 20:33:30 +0000880 /* Check if it was a dublicate request */
881 if(!gtp_dublicate(gsn, 0, peer, get_seq(pack))) return 0;
jjako52c24142002-12-16 13:33:51 +0000882
jjako08d331d2003-10-13 20:33:30 +0000883 /* Send off reply to request */
884 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
jjako52c24142002-12-16 13:33:51 +0000885}
886
887/* Handle a received echo reply */
jjako08d331d2003-10-13 20:33:30 +0000888int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
jjako52c24142002-12-16 13:33:51 +0000889 void *pack, unsigned len) {
890 union gtpie_member *ie[GTPIE_SIZE];
891 unsigned char recovery;
jjako08d331d2003-10-13 20:33:30 +0000892 void *cbp = NULL;
jjako52c24142002-12-16 13:33:51 +0000893 uint8_t type = 0;
jjako08d331d2003-10-13 20:33:30 +0000894 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +0000895
896 /* Remove packet from queue */
jjako08d331d2003-10-13 20:33:30 +0000897 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
jjako52c24142002-12-16 13:33:51 +0000898
jjako08d331d2003-10-13 20:33:30 +0000899 /* Extract information elements into a pointer array */
900 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
jjako52c24142002-12-16 13:33:51 +0000901 gsn->invalid++;
902 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
903 "Invalid message format");
jjako08d331d2003-10-13 20:33:30 +0000904 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +0000905 return EOF;
906 }
907
908 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
909 gsn->missing++;
910 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
911 "Missing mandatory field");
jjako08d331d2003-10-13 20:33:30 +0000912 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +0000913 return EOF;
914 }
915
jjako08d331d2003-10-13 20:33:30 +0000916 /* Echo reply packages does not have a cause information element */
917 /* Instead we return the recovery number in the callback function */
918 if (gsn->cb_conf) gsn->cb_conf(type, recovery, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +0000919
920 return 0;
921}
922
923/* Send off a Version Not Supported message */
924/* This message is somewhat special in that it actually is a
925 * response to some other message with unsupported GTP version
926 * For this reason it has parameters like a response, and does
927 * its own message transmission. No signalling queue is used
928 * The reply is sent to the peer IP and peer UDP. This means that
929 * the peer will be receiving a GTP0 message on a GTP1 port!
930 * In practice however this will never happen as a GTP0 GSN will
931 * only listen to the GTP0 port, and therefore will never receive
932 * anything else than GTP0 */
933
jjako08d331d2003-10-13 20:33:30 +0000934int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
935 int fd, void *pack, unsigned len)
jjako52c24142002-12-16 13:33:51 +0000936{
937 union gtp_packet packet;
jjako52c24142002-12-16 13:33:51 +0000938
jjako08d331d2003-10-13 20:33:30 +0000939 /* GTP 1 is the highest supported protocol */
jjako2c381332003-10-21 19:09:53 +0000940 int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
941 return gtp_notification(gsn, version, &packet, length,
942 peer, fd, 0);
jjako52c24142002-12-16 13:33:51 +0000943}
944
945/* Handle a Version Not Supported message */
jjako08d331d2003-10-13 20:33:30 +0000946int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
947 void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +0000948
jjako08d331d2003-10-13 20:33:30 +0000949 if (gsn->cb_unsup_ind) gsn->cb_unsup_ind(peer);
jjako52c24142002-12-16 13:33:51 +0000950
jjako52c24142002-12-16 13:33:51 +0000951 return 0;
952}
953
jjako2c381332003-10-21 19:09:53 +0000954/* Send off an Supported Extension Headers Notification */
955int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
956 int fd, void *pack, unsigned len)
957{
958 union gtp_packet packet;
959 int length = get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
960
961 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
962
963 if (version < 1)
964 return 0;
965
966 /* We report back that we support only PDCP PDU headers */
967 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T, sizeof(pdcp_pdu),
968 &pdcp_pdu);
969
970 return gtp_notification(gsn, version, &packet, length,
971 peer, fd, get_seq(pack));
972}
973
974/* Handle a Supported Extension Headers Notification */
975int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
976 void *pack, unsigned len) {
977
978 if (gsn->cb_extheader_ind) gsn->cb_extheader_ind(peer);
979
980 return 0;
981}
982
983
jjako52c24142002-12-16 13:33:51 +0000984/* ***********************************************************
985 * Session management messages
986 * Messages: create, update and delete PDP context
987 *
988 * Information storage
989 * Information storage for each PDP context is defined in
990 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
991 * PDP-address (IP address), sequence numbers, charging ID.
992 * For the SGSN it also includes radio related mobility
993 * information.
994 *************************************************************/
995
jjako08d331d2003-10-13 20:33:30 +0000996/* API: Send Create PDP Context Request */
997extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
998 void *cbp, struct in_addr* inetaddr) {
jjako52c24142002-12-16 13:33:51 +0000999 union gtp_packet packet;
jjako08d331d2003-10-13 20:33:30 +00001000 int length = get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
jjako2c381332003-10-21 19:09:53 +00001001 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001002
jjako2c381332003-10-21 19:09:53 +00001003 /* TODO: Secondary PDP Context Activation Procedure */
1004 /* In secondary activation procedure the PDP context is identified
1005 by tei in the header. The following fields are omitted: Selection
1006 mode, IMSI, MSISDN, End User Address, Access Point Name and
1007 Protocol Configuration Options */
1008
1009 if (pdp->secondary) {
1010 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
1011 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown linked PDP context");
1012 return EOF;
1013 }
1014 }
1015
1016 if (pdp->version == 0) {
jjako08d331d2003-10-13 20:33:30 +00001017 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
jjako52c24142002-12-16 13:33:51 +00001018 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako2c381332003-10-21 19:09:53 +00001019 }
jjako52c24142002-12-16 13:33:51 +00001020
jjako2c381332003-10-21 19:09:53 +00001021 if (pdp->version == 1) {
1022 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1023 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1024 sizeof(pdp->imsi), (uint8_t*) &pdp->imsi);
1025 }
jjako52c24142002-12-16 13:33:51 +00001026
jjako08d331d2003-10-13 20:33:30 +00001027 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1028 gsn->restart_counter);
jjako2c381332003-10-21 19:09:53 +00001029
1030 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1031 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1032 pdp->selmode);
jjako08d331d2003-10-13 20:33:30 +00001033
1034 if (pdp->version == 0) {
1035 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1036 pdp->fllu);
1037 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1038 pdp->fllc);
1039 }
1040
1041 if (pdp->version == 1) {
1042 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1043 pdp->teid_own);
jjako2c381332003-10-21 19:09:53 +00001044
1045 if (!pdp->teic_confirmed)
1046 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1047 pdp->teic_own);
jjako08d331d2003-10-13 20:33:30 +00001048 }
1049
1050 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1051 pdp->nsapi);
1052
jjako08d331d2003-10-13 20:33:30 +00001053
1054 if (pdp->version == 1) {
jjako2c381332003-10-21 19:09:53 +00001055 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1056 gtpie_tv1(packet.gtp1l.p, &length, GTP_MAX, GTPIE_NSAPI,
1057 linked_pdp->nsapi);
1058
jjako08d331d2003-10-13 20:33:30 +00001059 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1060 pdp->cch_pdp);
1061 }
1062
1063 /* TODO
1064 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1065 pdp->traceref);
1066 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1067 pdp->tracetype); */
1068
jjako2c381332003-10-21 19:09:53 +00001069 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1070 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1071 pdp->eua.l, pdp->eua.v);
1072
jjako08d331d2003-10-13 20:33:30 +00001073
jjako2c381332003-10-21 19:09:53 +00001074 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1075 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1076 pdp->apn_use.l, pdp->apn_use.v);
1077
1078 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1079 if (pdp->pco_req.l)
1080 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1081 pdp->pco_req.l, pdp->pco_req.v);
jjako08d331d2003-10-13 20:33:30 +00001082
1083 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1084 pdp->gsnlc.l, pdp->gsnlc.v);
1085 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1086 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001087
1088 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1089 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1090 pdp->msisdn.l, pdp->msisdn.v);
jjako08d331d2003-10-13 20:33:30 +00001091
1092 if (pdp->version == 1)
1093 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1094 pdp->qos_req.l, pdp->qos_req.v);
1095
1096
1097 if ((pdp->version == 1) && pdp->tft.l)
1098 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1099 pdp->tft.l, pdp->tft.v);
1100
1101 if ((pdp->version == 1) && pdp->triggerid.l)
1102 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1103 pdp->triggerid.l, pdp->triggerid.v);
1104
1105 if ((pdp->version == 1) && pdp->omcid.l)
1106 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1107 pdp->omcid.l, pdp->omcid.v);
1108
1109 gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
jjako52c24142002-12-16 13:33:51 +00001110
1111 return 0;
1112}
1113
jjako08d331d2003-10-13 20:33:30 +00001114/* API: Application response to context indication */
1115int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause) {
1116
1117 /* Now send off a reply to the peer */
1118 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1119
1120 if (cause != GTPCAUSE_ACC_REQ) {
1121 pdp_freepdp(pdp);
1122 }
1123
1124 return 0;
1125}
1126
1127/* API: Register create context indication callback */
1128int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
1129 int (*cb_create_context_ind) (struct pdp_t* pdp))
jjako52c24142002-12-16 13:33:51 +00001130{
jjako08d331d2003-10-13 20:33:30 +00001131 gsn->cb_create_context_ind = cb_create_context_ind;
1132 return 0;
1133}
1134
1135
1136/* Send Create PDP Context Response */
1137int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1138 uint8_t cause) {
jjako52c24142002-12-16 13:33:51 +00001139 union gtp_packet packet;
jjako08d331d2003-10-13 20:33:30 +00001140 int length = get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
jjako52c24142002-12-16 13:33:51 +00001141
jjako08d331d2003-10-13 20:33:30 +00001142 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00001143
1144 if (cause == GTPCAUSE_ACC_REQ) {
jjako08d331d2003-10-13 20:33:30 +00001145
1146 if (version == 0)
1147 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1148 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1149
1150 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
jjako52c24142002-12-16 13:33:51 +00001151 pdp->reorder);
jjako08d331d2003-10-13 20:33:30 +00001152 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
jjako52c24142002-12-16 13:33:51 +00001153 gsn->restart_counter);
jjako08d331d2003-10-13 20:33:30 +00001154
1155 if (version == 0) {
1156 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1157 pdp->fllu);
1158 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1159 pdp->fllc);
1160 }
1161
1162 if (version == 1) {
1163 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1164 pdp->teid_own);
1165 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1166 pdp->teic_own);
1167 }
1168
jjako2c381332003-10-21 19:09:53 +00001169 /* TODO: We use teic_own as charging ID */
jjako08d331d2003-10-13 20:33:30 +00001170 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
jjako2c381332003-10-21 19:09:53 +00001171 pdp->teic_own);
1172
jjako08d331d2003-10-13 20:33:30 +00001173 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
jjako52c24142002-12-16 13:33:51 +00001174 pdp->eua.l, pdp->eua.v);
1175
1176 if (pdp->pco_neg.l) { /* Optional PCO */
jjako08d331d2003-10-13 20:33:30 +00001177 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
jjako52c24142002-12-16 13:33:51 +00001178 pdp->pco_neg.l, pdp->pco_neg.v);
1179 }
1180
jjako08d331d2003-10-13 20:33:30 +00001181 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
jjako52c24142002-12-16 13:33:51 +00001182 pdp->gsnlc.l, pdp->gsnlc.v);
jjako08d331d2003-10-13 20:33:30 +00001183 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
jjako52c24142002-12-16 13:33:51 +00001184 pdp->gsnlu.l, pdp->gsnlu.v);
jjako08d331d2003-10-13 20:33:30 +00001185
1186 if (version == 1)
1187 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1188 pdp->qos_neg.l, pdp->qos_neg.v);
1189
1190 /* TODO: Charging gateway address */
jjako52c24142002-12-16 13:33:51 +00001191 }
1192
jjako08d331d2003-10-13 20:33:30 +00001193 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1194 pdp->fd, pdp->seq, pdp->tid);
jjako52c24142002-12-16 13:33:51 +00001195}
1196
1197/* Handle Create PDP Context Request */
1198int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00001199 struct sockaddr_in *peer, int fd,
1200 void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +00001201 struct pdp_t *pdp, *pdp_old;
1202 struct pdp_t pdp_buf;
1203 union gtpie_member* ie[GTPIE_SIZE];
1204 uint8_t recovery;
jjako52c24142002-12-16 13:33:51 +00001205
jjako08d331d2003-10-13 20:33:30 +00001206 uint16_t seq = get_seq(pack);
1207 int hlen = get_hlen(pack);
jjako2c381332003-10-21 19:09:53 +00001208 uint8_t linked_nsapi = 0;
1209 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00001210
jjako2c381332003-10-21 19:09:53 +00001211 if(!gtp_dublicate(gsn, version, peer, seq)) return 0;
jjako08d331d2003-10-13 20:33:30 +00001212
1213 pdp = &pdp_buf;
1214 memset(pdp, 0, sizeof(struct pdp_t));
1215
1216 if (version == 0) {
1217 pdp->imsi = ((union gtp_packet*)pack)->gtp0.h.tid & 0x0fffffffffffffff;
1218 pdp->nsapi = (((union gtp_packet*)pack)->gtp0.h.tid & 0xf000000000000000) >> 60;
jjako52c24142002-12-16 13:33:51 +00001219 }
1220
jjako08d331d2003-10-13 20:33:30 +00001221 pdp->seq = seq;
1222 pdp->sa_peer = *peer;
1223 pdp->fd = fd;
1224 pdp->version = version;
1225
jjako52c24142002-12-16 13:33:51 +00001226 /* Decode information elements */
jjako08d331d2003-10-13 20:33:30 +00001227 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
jjako52c24142002-12-16 13:33:51 +00001228 gsn->invalid++;
1229 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1230 "Invalid message format");
1231 if (0 == version)
1232 return EOF;
1233 else
jjako08d331d2003-10-13 20:33:30 +00001234 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_INVALID_MESSAGE);
jjako52c24142002-12-16 13:33:51 +00001235 }
1236
jjako2c381332003-10-21 19:09:53 +00001237 if (version == 1) {
1238 /* Linked NSAPI (conditional) */
1239 /* If included this is the Secondary PDP Context Activation Procedure */
1240 /* In secondary activation IMSI is not included, so the context must be */
1241 /* identified by the tei */
1242 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
1243
1244 /* Find the primary PDP context */
1245 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1246 gsn->incorrect++;
1247 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1248 "Incorrect optional information field");
1249 return gtp_create_pdp_resp(gsn, version, pdp,
1250 GTPCAUSE_OPT_IE_INCORRECT);
1251 }
1252
1253 /* Check that the primary PDP context matches linked nsapi */
1254 if (linked_pdp->nsapi != linked_nsapi) {
1255 gsn->incorrect++;
1256 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1257 "Incorrect optional information field");
1258 return gtp_create_pdp_resp(gsn, version, pdp,
1259 GTPCAUSE_OPT_IE_INCORRECT);
1260 }
1261
1262 /* Copy parameters from primary context */
1263 pdp->selmode = linked_pdp->selmode;
1264 pdp->imsi = linked_pdp->imsi;
1265 pdp->msisdn = linked_pdp->msisdn;
1266 pdp->eua = linked_pdp->eua;
1267 pdp->pco_req = linked_pdp->pco_req;
1268 pdp->apn_req = linked_pdp->apn_req;
1269 pdp->teic_gn = linked_pdp->teic_gn;
1270 pdp->secondary = 1;
1271 }
1272 } /* if (version == 1) */
1273
jjako08d331d2003-10-13 20:33:30 +00001274 if (version == 0) {
1275 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1276 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1277 gsn->missing++;
1278 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1279 "Missing mandatory information field");
1280 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_MAN_IE_MISSING);
1281 }
jjako52c24142002-12-16 13:33:51 +00001282 }
jjako2c381332003-10-21 19:09:53 +00001283
1284 if ((version == 1) && (!linked_pdp)) {
1285 /* Not Secondary PDP Context Activation Procedure */
jjako08d331d2003-10-13 20:33:30 +00001286 /* IMSI (conditional) */
1287 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1288 gsn->missing++;
1289 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1290 "Missing mandatory information field");
1291 return gtp_create_pdp_resp(gsn, version, pdp,
1292 GTPCAUSE_MAN_IE_MISSING);
1293 }
1294 }
jjako2c381332003-10-21 19:09:53 +00001295
jjako08d331d2003-10-13 20:33:30 +00001296 /* Recovery (optional) */
jjako52c24142002-12-16 13:33:51 +00001297 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1298 /* TODO: Handle received recovery IE */
1299 }
jjako2c381332003-10-21 19:09:53 +00001300
jjako08d331d2003-10-13 20:33:30 +00001301 /* Selection mode (conditional) */
jjako2c381332003-10-21 19:09:53 +00001302 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1303 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1304 &pdp->selmode, sizeof(pdp->selmode))) {
1305 gsn->missing++;
1306 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1307 "Missing mandatory information field");
1308 return gtp_create_pdp_resp(gsn, version, pdp,
1309 GTPCAUSE_MAN_IE_MISSING);
1310 }
jjako52c24142002-12-16 13:33:51 +00001311 }
1312
jjako08d331d2003-10-13 20:33:30 +00001313 if (version == 0) {
1314 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1315 gsn->missing++;
1316 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1317 "Missing mandatory information field");
1318 return gtp_create_pdp_resp(gsn, version, pdp,
1319 GTPCAUSE_MAN_IE_MISSING);
1320 }
1321
1322 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1323 gsn->missing++;
1324 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1325 "Missing mandatory information field");
1326 return gtp_create_pdp_resp(gsn, version, pdp,
1327 GTPCAUSE_MAN_IE_MISSING);
1328 }
jjako52c24142002-12-16 13:33:51 +00001329 }
jjako2c381332003-10-21 19:09:53 +00001330
1331
jjako08d331d2003-10-13 20:33:30 +00001332 if (version == 1) {
1333 /* TEID (mandatory) */
1334 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1335 gsn->missing++;
1336 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1337 "Missing mandatory information field");
1338 return gtp_create_pdp_resp(gsn, version, pdp,
1339 GTPCAUSE_MAN_IE_MISSING);
1340 }
1341
1342 /* TEIC (conditional) */
jjako2c381332003-10-21 19:09:53 +00001343 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1344 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1345 gsn->missing++;
1346 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1347 "Missing mandatory information field");
1348 return gtp_create_pdp_resp(gsn, version, pdp,
1349 GTPCAUSE_MAN_IE_MISSING);
1350 }
jjako08d331d2003-10-13 20:33:30 +00001351 }
jjako52c24142002-12-16 13:33:51 +00001352 }
1353
jjako2c381332003-10-21 19:09:53 +00001354 /* NSAPI (mandatory) */
1355 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1356 gsn->missing++;
1357 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1358 "Missing mandatory information field");
1359 return gtp_create_pdp_resp(gsn, version, pdp,
1360 GTPCAUSE_MAN_IE_MISSING);
1361 }
1362
1363
jjako08d331d2003-10-13 20:33:30 +00001364 /* Charging Characteriatics (optional) */
1365 /* Trace reference (optional) */
1366 /* Trace type (optional) */
1367 /* Charging Characteriatics (optional) */
jjako2c381332003-10-21 19:09:53 +00001368
1369 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1370 /* End User Address (conditional) */
1371 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
jjako52c24142002-12-16 13:33:51 +00001372 &pdp->eua.v, sizeof(pdp->eua.v))) {
jjako2c381332003-10-21 19:09:53 +00001373 gsn->missing++;
1374 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1375 "Missing mandatory information field");
1376 return gtp_create_pdp_resp(gsn, version, pdp,
1377 GTPCAUSE_MAN_IE_MISSING);
1378 }
1379
1380 /* APN */
1381 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
jjako52c24142002-12-16 13:33:51 +00001382 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
jjako2c381332003-10-21 19:09:53 +00001383 gsn->missing++;
1384 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1385 "Missing mandatory information field");
1386 return gtp_create_pdp_resp(gsn, version, pdp,
1387 GTPCAUSE_MAN_IE_MISSING);
1388 }
1389
1390 /* Extract protocol configuration options (optional) */
1391 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1392 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1393 }
jjako52c24142002-12-16 13:33:51 +00001394 }
1395
jjako08d331d2003-10-13 20:33:30 +00001396 /* SGSN address for signalling (mandatory) */
jjako52c24142002-12-16 13:33:51 +00001397 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1398 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1399 gsn->missing++;
1400 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1401 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00001402 return gtp_create_pdp_resp(gsn, version, pdp,
jjako52c24142002-12-16 13:33:51 +00001403 GTPCAUSE_MAN_IE_MISSING);
1404 }
1405
jjako08d331d2003-10-13 20:33:30 +00001406 /* SGSN address for user traffic (mandatory) */
jjako52c24142002-12-16 13:33:51 +00001407 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1408 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1409 gsn->missing++;
1410 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1411 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00001412 return gtp_create_pdp_resp(gsn, version, pdp,
jjako52c24142002-12-16 13:33:51 +00001413 GTPCAUSE_MAN_IE_MISSING);
1414 }
1415
jjako2c381332003-10-21 19:09:53 +00001416 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1417 /* MSISDN (conditional) */
1418 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1419 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1420 gsn->missing++;
1421 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1422 "Missing mandatory information field");
1423 return gtp_create_pdp_resp(gsn, version, pdp,
1424 GTPCAUSE_MAN_IE_MISSING);
1425 }
jjako52c24142002-12-16 13:33:51 +00001426 }
1427
jjako08d331d2003-10-13 20:33:30 +00001428 if (version == 1) {
1429 /* QoS (mandatory) */
1430 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1431 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1432 gsn->missing++;
1433 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1434 "Missing mandatory information field");
1435 return gtp_create_pdp_resp(gsn, version, pdp,
1436 GTPCAUSE_MAN_IE_MISSING);
1437 }
1438
1439 /* TFT (conditional) */
1440 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1441 &pdp->tft.v, sizeof(pdp->tft.v))) {
1442 }
jjako2c381332003-10-21 19:09:53 +00001443
jjako08d331d2003-10-13 20:33:30 +00001444 /* Trigger ID */
1445 /* OMC identity */
1446 }
1447
1448 /* Initialize our own IP addresses */
jjako52c24142002-12-16 13:33:51 +00001449 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1450 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
jjako2c381332003-10-21 19:09:53 +00001451
jjako2e840a32003-01-28 16:05:18 +00001452 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Before pdp_tidget\n");
jjako2c381332003-10-21 19:09:53 +00001453
jjako08d331d2003-10-13 20:33:30 +00001454 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
jjako52c24142002-12-16 13:33:51 +00001455 /* Found old pdp with same tid. Now the voodoo begins! */
jjako08d331d2003-10-13 20:33:30 +00001456 /* 09.60 / 29.060 allows create on existing context to "steal" */
1457 /* the context which was allready established */
jjako52c24142002-12-16 13:33:51 +00001458 /* We check that the APN, selection mode and MSISDN is the same */
jjako2e840a32003-01-28 16:05:18 +00001459 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Old context found\n");
jjako08d331d2003-10-13 20:33:30 +00001460 if ((pdp->apn_req.l == pdp_old->apn_req.l)
jjako52c24142002-12-16 13:33:51 +00001461 && (!memcmp(pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1462 && (pdp->selmode == pdp_old->selmode)
1463 && (pdp->msisdn.l == pdp_old->msisdn.l)
1464 && (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l))) {
1465 /* OK! We are dealing with the same APN. We will copy new
1466 * parameters to the old pdp and send off confirmation
1467 * We ignore the following information elements:
1468 * QoS: MS will get originally negotiated QoS.
1469 * End user address (EUA). MS will get old EUA anyway.
1470 * Protocol configuration option (PCO): Only application can verify */
jjako2e840a32003-01-28 16:05:18 +00001471
1472 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Old context found\n");
jjako52c24142002-12-16 13:33:51 +00001473
1474 /* Copy remote flow label */
1475 pdp_old->flru = pdp->flru;
1476 pdp_old->flrc = pdp->flrc;
1477
jjako08d331d2003-10-13 20:33:30 +00001478 /* Copy remote tei */
1479 pdp_old->teid_gn = pdp->teid_gn;
1480 pdp_old->teic_gn = pdp->teic_gn;
1481
jjako52c24142002-12-16 13:33:51 +00001482 /* Copy peer GSN address */
1483 pdp_old->gsnrc.l = pdp->gsnrc.l;
1484 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1485 pdp_old->gsnru.l = pdp->gsnru.l;
1486 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
jjako2c381332003-10-21 19:09:53 +00001487
1488 /* Copy request parameters */
1489 pdp_old->seq = pdp->seq;
1490 pdp_old->sa_peer = pdp->sa_peer;
1491 pdp_old->fd = pdp->fd = fd;
1492 pdp_old->version = pdp->version = version;
1493
1494 /* Switch to using the old pdp context */
jjako52c24142002-12-16 13:33:51 +00001495 pdp = pdp_old;
1496
1497 /* Confirm to peer that things were "successful" */
jjako08d331d2003-10-13 20:33:30 +00001498 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_ACC_REQ);
jjako52c24142002-12-16 13:33:51 +00001499 }
1500 else { /* This is not the same PDP context. Delete the old one. */
jjako2e840a32003-01-28 16:05:18 +00001501
1502 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Deleting old context\n");
jjako52c24142002-12-16 13:33:51 +00001503
1504 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp_old);
1505 pdp_freepdp(pdp_old);
jjako08d331d2003-10-13 20:33:30 +00001506
jjako2e840a32003-01-28 16:05:18 +00001507 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Deleted...\n");
jjako52c24142002-12-16 13:33:51 +00001508 }
1509 }
1510
jjako08d331d2003-10-13 20:33:30 +00001511 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
jjako52c24142002-12-16 13:33:51 +00001512
1513 /* Callback function to validata login */
jjako08d331d2003-10-13 20:33:30 +00001514 if (gsn->cb_create_context_ind !=0)
1515 return gsn->cb_create_context_ind(pdp);
jjako52c24142002-12-16 13:33:51 +00001516 else {
jjako08d331d2003-10-13 20:33:30 +00001517 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1518 "No create_context_ind callback defined");
1519 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_NOT_SUPPORTED);
jjako52c24142002-12-16 13:33:51 +00001520 }
1521}
1522
1523
1524/* Handle Create PDP Context Response */
1525int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00001526 struct sockaddr_in *peer,
1527 void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +00001528 struct pdp_t *pdp;
1529 union gtpie_member *ie[GTPIE_SIZE];
1530 uint8_t cause, recovery;
jjako08d331d2003-10-13 20:33:30 +00001531 void *cbp = NULL;
jjako52c24142002-12-16 13:33:51 +00001532 uint8_t type = 0;
jjako08d331d2003-10-13 20:33:30 +00001533 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001534
1535 /* Remove packet from queue */
jjako08d331d2003-10-13 20:33:30 +00001536 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
jjako52c24142002-12-16 13:33:51 +00001537
1538 /* Find the context in question */
jjako08d331d2003-10-13 20:33:30 +00001539 if (pdp_getgtp1(&pdp, get_tei(pack))) {
jjako52c24142002-12-16 13:33:51 +00001540 gsn->err_unknownpdp++;
1541 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1542 "Unknown PDP context");
jjako08d331d2003-10-13 20:33:30 +00001543 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +00001544 return EOF;
1545 }
1546
jjako2c381332003-10-21 19:09:53 +00001547 /* Register that we have received a valid teic from GGSN */
1548 pdp->teic_confirmed = 1;
1549
jjako52c24142002-12-16 13:33:51 +00001550 /* Decode information elements */
jjako08d331d2003-10-13 20:33:30 +00001551 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
jjako52c24142002-12-16 13:33:51 +00001552 gsn->invalid++;
1553 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1554 "Invalid message format");
jjako08d331d2003-10-13 20:33:30 +00001555 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001556 return EOF;
1557 }
1558
1559 /* Extract cause value (mandatory) */
1560 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1561 gsn->missing++;
1562 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1563 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00001564 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001565 return EOF;
1566 }
1567
1568 /* Extract recovery (optional) */
1569 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1570 /* TODO: Handle received recovery IE */
1571 }
1572
1573 /* Extract protocol configuration options (optional) */
1574 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1575 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
jjako52c24142002-12-16 13:33:51 +00001576 }
1577
1578 /* Check all conditional information elements */
1579 if (GTPCAUSE_ACC_REQ == cause) {
1580
jjako08d331d2003-10-13 20:33:30 +00001581 if (version == 0) {
1582 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1583 &pdp->qos_neg0, sizeof(pdp->qos_neg0))) {
1584 gsn->missing++;
1585 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1586 "Missing conditional information field");
1587 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1588 return EOF;
1589 }
jjako52c24142002-12-16 13:33:51 +00001590 }
jjako52c24142002-12-16 13:33:51 +00001591
1592 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1593 gsn->missing++;
1594 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1595 "Missing conditional information field");
jjako08d331d2003-10-13 20:33:30 +00001596 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001597 return EOF;
1598 }
1599
jjako08d331d2003-10-13 20:33:30 +00001600 if (version == 0) {
1601 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1602 gsn->missing++;
1603 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1604 "Missing conditional information field");
1605 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1606 return EOF;
1607 }
jjako52c24142002-12-16 13:33:51 +00001608
jjako08d331d2003-10-13 20:33:30 +00001609 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1610 gsn->missing++;
1611 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1612 "Missing conditional information field");
1613 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1614 return EOF;
1615 }
1616 }
1617
1618 if (version == 1) {
1619 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1620 gsn->missing++;
1621 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1622 "Missing conditional information field");
1623 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1624 return EOF;
1625 }
1626
1627 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1628 gsn->missing++;
1629 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1630 "Missing conditional information field");
1631 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1632 return EOF;
1633 }
jjako52c24142002-12-16 13:33:51 +00001634 }
1635
1636 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1637 gsn->missing++;
1638 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1639 "Missing conditional information field");
jjako08d331d2003-10-13 20:33:30 +00001640 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001641 }
1642
1643 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1644 &pdp->eua.v, sizeof(pdp->eua.v))) {
1645 gsn->missing++;
1646 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1647 "Missing conditional information field");
jjako08d331d2003-10-13 20:33:30 +00001648 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001649 return EOF;
1650 }
1651
1652 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1653 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1654 gsn->missing++;
1655 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1656 "Missing conditional information field");
jjako08d331d2003-10-13 20:33:30 +00001657 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001658 return EOF;
1659 }
1660
1661 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1662 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1663 gsn->missing++;
1664 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1665 "Missing conditional information field");
jjako08d331d2003-10-13 20:33:30 +00001666 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001667 return EOF;
1668 }
jjako52c24142002-12-16 13:33:51 +00001669
jjako08d331d2003-10-13 20:33:30 +00001670 if (version == 1) {
1671 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1672 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1673 gsn->missing++;
1674 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1675 "Missing conditional information field");
1676 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1677 return EOF;
1678 }
1679 }
1680
1681 }
1682
1683 if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00001684
1685 return 0;
1686}
1687
jjako52c24142002-12-16 13:33:51 +00001688
jjako08d331d2003-10-13 20:33:30 +00001689/* API: Send Update PDP Context Request */
1690int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
1691 struct in_addr* inetaddr) {
1692 union gtp_packet packet;
1693 int length = get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
jjako52c24142002-12-16 13:33:51 +00001694
jjako08d331d2003-10-13 20:33:30 +00001695 if (pdp->version == 0)
1696 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1697 sizeof(pdp->qos_req0), pdp->qos_req0);
jjako2c381332003-10-21 19:09:53 +00001698
1699 /* Include IMSI if updating with unknown teic_gn */
1700 if ((pdp->version == 1) && (!pdp->teic_gn))
jjako08d331d2003-10-13 20:33:30 +00001701 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1702 sizeof(pdp->imsi), (uint8_t*) &pdp->imsi);
jjako2c381332003-10-21 19:09:53 +00001703
jjako08d331d2003-10-13 20:33:30 +00001704 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
jjako52c24142002-12-16 13:33:51 +00001705 gsn->restart_counter);
jjako2c381332003-10-21 19:09:53 +00001706
jjako08d331d2003-10-13 20:33:30 +00001707 if (pdp->version == 0) {
1708 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
jjako52c24142002-12-16 13:33:51 +00001709 pdp->fllu);
jjako08d331d2003-10-13 20:33:30 +00001710 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
jjako52c24142002-12-16 13:33:51 +00001711 pdp->fllc);
jjako52c24142002-12-16 13:33:51 +00001712 }
jjako2c381332003-10-21 19:09:53 +00001713
jjako08d331d2003-10-13 20:33:30 +00001714 if (pdp->version == 1) {
1715 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1716 pdp->teid_own);
jjako52c24142002-12-16 13:33:51 +00001717
jjako2c381332003-10-21 19:09:53 +00001718 if (!pdp->teic_confirmed)
1719 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1720 pdp->teic_own);
1721 }
1722
jjako08d331d2003-10-13 20:33:30 +00001723 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1724 pdp->nsapi);
jjako2c381332003-10-21 19:09:53 +00001725
jjako08d331d2003-10-13 20:33:30 +00001726 /* TODO
jjako2c381332003-10-21 19:09:53 +00001727 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1728 pdp->traceref);
1729 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1730 pdp->tracetype); */
1731
jjako08d331d2003-10-13 20:33:30 +00001732 /* TODO if ggsn update message
jjako2c381332003-10-21 19:09:53 +00001733 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1734 pdp->eua.l, pdp->eua.v);
jjako08d331d2003-10-13 20:33:30 +00001735 */
jjako2c381332003-10-21 19:09:53 +00001736
jjako08d331d2003-10-13 20:33:30 +00001737 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1738 pdp->gsnlc.l, pdp->gsnlc.v);
1739 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1740 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001741
jjako08d331d2003-10-13 20:33:30 +00001742 if (pdp->version == 1)
1743 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1744 pdp->qos_req.l, pdp->qos_req.v);
jjako2c381332003-10-21 19:09:53 +00001745
1746
jjako08d331d2003-10-13 20:33:30 +00001747 if ((pdp->version == 1) && pdp->tft.l)
1748 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1749 pdp->tft.l, pdp->tft.v);
1750
1751 if ((pdp->version == 1) && pdp->triggerid.l)
1752 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1753 pdp->triggerid.l, pdp->triggerid.v);
1754
1755 if ((pdp->version == 1) && pdp->omcid.l)
1756 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1757 pdp->omcid.l, pdp->omcid.v);
1758
1759 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1760
1761 return 0;
jjako52c24142002-12-16 13:33:51 +00001762}
1763
jjako08d331d2003-10-13 20:33:30 +00001764
1765/* Send Update PDP Context Response */
1766int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1767 struct sockaddr_in *peer, int fd,
1768 void *pack, unsigned len,
1769 struct pdp_t *pdp, uint8_t cause) {
1770
1771 union gtp_packet packet;
1772 int length = get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
1773
1774 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
1775
1776 if (cause == GTPCAUSE_ACC_REQ) {
1777
1778 if (version == 0)
1779 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1780 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1781
1782 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1783 gsn->restart_counter);
1784
1785 if (version == 0) {
1786 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1787 pdp->fllu);
1788 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1789 pdp->fllc);
1790 }
1791
1792 if (version == 1) {
1793 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1794 pdp->teid_own);
jjako2c381332003-10-21 19:09:53 +00001795
1796 if (!pdp->teic_confirmed)
1797 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1798 pdp->teic_own);
jjako08d331d2003-10-13 20:33:30 +00001799 }
jjako2c381332003-10-21 19:09:53 +00001800
1801 /* TODO we use teid_own as charging ID address */
jjako08d331d2003-10-13 20:33:30 +00001802 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
jjako2c381332003-10-21 19:09:53 +00001803 pdp->teid_own);
1804
jjako08d331d2003-10-13 20:33:30 +00001805 /* If ggsn
jjako2c381332003-10-21 19:09:53 +00001806 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1807 pdp->eua.l, pdp->eua.v); */
1808
jjako08d331d2003-10-13 20:33:30 +00001809 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1810 pdp->gsnlc.l, pdp->gsnlc.v);
1811 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1812 pdp->gsnlu.l, pdp->gsnlu.v);
jjako2c381332003-10-21 19:09:53 +00001813
jjako08d331d2003-10-13 20:33:30 +00001814 if (version == 1)
1815 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1816 pdp->qos_neg.l, pdp->qos_neg.v);
jjako2c381332003-10-21 19:09:53 +00001817
jjako08d331d2003-10-13 20:33:30 +00001818 /* TODO: Charging gateway address */
1819 }
jjako2c381332003-10-21 19:09:53 +00001820
1821 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1822 fd, get_seq(pack), get_tid(pack));
jjako08d331d2003-10-13 20:33:30 +00001823}
1824
1825
jjako52c24142002-12-16 13:33:51 +00001826/* Handle Update PDP Context Request */
1827int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00001828 struct sockaddr_in *peer, int fd,
1829 void *pack, unsigned len) {
1830 struct pdp_t *pdp;
1831 struct pdp_t pdp_backup;
jjako52c24142002-12-16 13:33:51 +00001832 union gtpie_member* ie[GTPIE_SIZE];
1833 uint8_t recovery;
1834
jjako08d331d2003-10-13 20:33:30 +00001835 uint16_t seq = get_seq(pack);
1836 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00001837
jjako08d331d2003-10-13 20:33:30 +00001838 uint64_t imsi;
1839 uint8_t nsapi;
1840
jjako52c24142002-12-16 13:33:51 +00001841 /* Is this a dublicate ? */
jjako08d331d2003-10-13 20:33:30 +00001842 if(!gtp_dublicate(gsn, version, peer, seq)) {
jjako52c24142002-12-16 13:33:51 +00001843 return 0; /* We allready send of response once */
1844 }
jjako2c381332003-10-21 19:09:53 +00001845
jjako52c24142002-12-16 13:33:51 +00001846
1847 /* Decode information elements */
jjako08d331d2003-10-13 20:33:30 +00001848 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
jjako52c24142002-12-16 13:33:51 +00001849 gsn->invalid++;
1850 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1851 "Invalid message format");
1852 if (0 == version)
1853 return EOF;
1854 else
jjako08d331d2003-10-13 20:33:30 +00001855 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1856 NULL, GTPCAUSE_INVALID_MESSAGE);
jjako52c24142002-12-16 13:33:51 +00001857 }
1858
jjako08d331d2003-10-13 20:33:30 +00001859 /* Finding PDP: */
1860 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1861 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1862 /* we have to use the tunnel endpoint identifier */
1863 if (version == 0) {
1864 imsi = ((union gtp_packet*)pack)->gtp0.h.tid & 0x0fffffffffffffff;
1865 nsapi = (((union gtp_packet*)pack)->gtp0.h.tid & 0xf000000000000000) >> 60;
jjako2c381332003-10-21 19:09:53 +00001866
jjako08d331d2003-10-13 20:33:30 +00001867 /* Find the context in question */
1868 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1869 gsn->err_unknownpdp++;
1870 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1871 "Unknown PDP context");
1872 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1873 NULL, GTPCAUSE_NON_EXIST);
1874 }
jjako52c24142002-12-16 13:33:51 +00001875 }
jjako08d331d2003-10-13 20:33:30 +00001876 else if (version == 1) {
1877 /* NSAPI (mandatory) */
1878 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
1879 gsn->missing++;
1880 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1881 "Missing mandatory information field");
1882 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1883 NULL, GTPCAUSE_MAN_IE_MISSING);
1884 }
jjako2c381332003-10-21 19:09:53 +00001885
jjako08d331d2003-10-13 20:33:30 +00001886 /* IMSI (conditional) */
1887 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
1888 /* Find the context in question */
1889 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1890 gsn->err_unknownpdp++;
1891 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1892 "Unknown PDP context");
1893 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1894 NULL, GTPCAUSE_NON_EXIST);
1895 }
1896 }
1897 else {
1898 /* Find the context in question */
1899 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1900 gsn->err_unknownpdp++;
1901 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1902 "Unknown PDP context");
1903 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1904 NULL, GTPCAUSE_NON_EXIST);
1905 }
1906 }
1907 }
1908 else {
1909 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
1910 return EOF;
1911 }
jjako2c381332003-10-21 19:09:53 +00001912
jjako08d331d2003-10-13 20:33:30 +00001913 /* Make a backup copy in case anything is wrong */
1914 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
1915
1916 if (version == 0) {
1917 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1918 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1919 gsn->missing++;
1920 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1921 "Missing mandatory information field");
1922 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1923 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1924 pdp, GTPCAUSE_MAN_IE_MISSING);
1925 }
1926 }
1927
1928 /* Recovery (optional) */
jjako52c24142002-12-16 13:33:51 +00001929 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1930 /* TODO: Handle received recovery IE */
1931 }
1932
jjako08d331d2003-10-13 20:33:30 +00001933 if (version == 0) {
1934 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1935 gsn->missing++;
1936 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1937 "Missing mandatory information field");
1938 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1939 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1940 GTPCAUSE_MAN_IE_MISSING);
1941 }
1942
1943 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1944 gsn->missing++;
1945 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1946 "Missing mandatory information field");
1947 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1948 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1949 GTPCAUSE_MAN_IE_MISSING);
1950 }
1951 }
1952
1953
1954 if (version == 1) {
1955 /* TEID (mandatory) */
1956 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1957 gsn->missing++;
1958 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1959 "Missing mandatory information field");
1960 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1961 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1962 GTPCAUSE_MAN_IE_MISSING);
1963 }
jjako2c381332003-10-21 19:09:53 +00001964
jjako08d331d2003-10-13 20:33:30 +00001965 /* TEIC (conditional) */
1966 /* If TEIC is not included it means that we have allready received it */
jjako2c381332003-10-21 19:09:53 +00001967 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
1968 /* all updated contexts, or only for one of the linked contexts */
1969 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
1970
jjako08d331d2003-10-13 20:33:30 +00001971 /* NSAPI (mandatory) */
1972 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1973 gsn->missing++;
1974 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1975 "Missing mandatory information field");
1976 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1977 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1978 GTPCAUSE_MAN_IE_MISSING);
1979 }
1980 }
1981
1982 /* Trace reference (optional) */
1983 /* Trace type (optional) */
1984
1985 /* End User Address (conditional) TODO: GGSN Initiated
1986 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1987 &pdp->eua.v, sizeof(pdp->eua.v))) {
jjako52c24142002-12-16 13:33:51 +00001988 gsn->missing++;
1989 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1990 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00001991 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1992 return gtp_update_pdp_resp(gsn, version, pdp,
jjako52c24142002-12-16 13:33:51 +00001993 GTPCAUSE_MAN_IE_MISSING);
jjako08d331d2003-10-13 20:33:30 +00001994 } */
jjako52c24142002-12-16 13:33:51 +00001995
jjako08d331d2003-10-13 20:33:30 +00001996
1997 /* SGSN address for signalling (mandatory) */
1998 /* It is weird that this is mandatory when TEIC is conditional */
1999 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2000 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
jjako52c24142002-12-16 13:33:51 +00002001 gsn->missing++;
2002 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2003 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00002004 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2005 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
jjako52c24142002-12-16 13:33:51 +00002006 GTPCAUSE_MAN_IE_MISSING);
2007 }
2008
jjako08d331d2003-10-13 20:33:30 +00002009 /* SGSN address for user traffic (mandatory) */
2010 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2011 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
jjako52c24142002-12-16 13:33:51 +00002012 gsn->missing++;
2013 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2014 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00002015 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2016 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
jjako52c24142002-12-16 13:33:51 +00002017 GTPCAUSE_MAN_IE_MISSING);
2018 }
jjako08d331d2003-10-13 20:33:30 +00002019
2020 if (version == 1) {
2021 /* QoS (mandatory) */
2022 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2023 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2024 gsn->missing++;
2025 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2026 "Missing mandatory information field");
2027 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2028 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2029 GTPCAUSE_MAN_IE_MISSING);
2030 }
jjako52c24142002-12-16 13:33:51 +00002031
jjako08d331d2003-10-13 20:33:30 +00002032 /* TFT (conditional) */
2033 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2034 &pdp->tft.v, sizeof(pdp->tft.v))) {
2035 }
2036
2037 /* OMC identity */
jjako52c24142002-12-16 13:33:51 +00002038 }
2039
jjako52c24142002-12-16 13:33:51 +00002040 /* Confirm to peer that things were "successful" */
jjako08d331d2003-10-13 20:33:30 +00002041 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
jjako52c24142002-12-16 13:33:51 +00002042 GTPCAUSE_ACC_REQ);
2043}
2044
2045
2046/* Handle Update PDP Context Response */
2047int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
2048 struct sockaddr_in *peer,
2049 void *pack, unsigned len) {
2050 struct pdp_t *pdp;
2051 union gtpie_member *ie[GTPIE_SIZE];
2052 uint8_t cause, recovery;
jjako08d331d2003-10-13 20:33:30 +00002053 void *cbp = NULL;
jjako52c24142002-12-16 13:33:51 +00002054 uint8_t type = 0;
2055
2056 /* Remove packet from queue */
jjako08d331d2003-10-13 20:33:30 +00002057 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp)) return EOF;
jjako52c24142002-12-16 13:33:51 +00002058
2059 /* Find the context in question */
2060 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet*)pack)->gtp0.h.flow))) {
2061 gsn->err_unknownpdp++;
2062 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2063 "Unknown PDP context");
jjako08d331d2003-10-13 20:33:30 +00002064 if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +00002065 return EOF;
2066 }
2067
jjako2c381332003-10-21 19:09:53 +00002068 /* Register that we have received a valid teic from GGSN */
2069 pdp->teic_confirmed = 1;
2070
jjako52c24142002-12-16 13:33:51 +00002071 /* Decode information elements */
jjako08d331d2003-10-13 20:33:30 +00002072 if (gtpie_decaps(ie, 0, pack+GTP0_HEADER_SIZE, len-GTP0_HEADER_SIZE)) {
jjako52c24142002-12-16 13:33:51 +00002073 gsn->invalid++;
2074 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2075 "Invalid message format");
jjako08d331d2003-10-13 20:33:30 +00002076 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00002077 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2078 pdp_freepdp(pdp);
2079 return EOF;
2080 }
2081
2082 /* Extract cause value (mandatory) */
2083 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2084 gsn->missing++;
2085 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2086 "Missing mandatory information field");
jjako08d331d2003-10-13 20:33:30 +00002087 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00002088 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2089 pdp_freepdp(pdp);
2090 return EOF;
2091 }
2092
2093 /* Extract recovery (optional) */
2094 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2095 /* TODO: Handle received recovery IE */
2096 }
2097
2098 /* Check all conditional information elements */
2099 if (GTPCAUSE_ACC_REQ != cause) {
jjako08d331d2003-10-13 20:33:30 +00002100 if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00002101 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2102 pdp_freepdp(pdp);
2103 return 0;
2104 }
2105 else {
2106 /* Check for missing conditionary information elements */
2107 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2108 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2109 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2110 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2111 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2112 gtpie_exist(ie, GTPIE_EUA, 0) &&
2113 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2114 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2115 gsn->missing++;
2116 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2117 "Missing conditional information field");
jjako08d331d2003-10-13 20:33:30 +00002118 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00002119 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2120 pdp_freepdp(pdp);
2121 return EOF;
2122 }
2123
2124 /* Update pdp with new values */
2125 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2126 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2127 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2128 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2129 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2130 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2131 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2132 &pdp->eua.v, sizeof(pdp->eua.v));
2133 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2134 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2135 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2136 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2137
jjako08d331d2003-10-13 20:33:30 +00002138 if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
jjako52c24142002-12-16 13:33:51 +00002139 return 0; /* Succes */
2140 }
2141}
2142
jjako52c24142002-12-16 13:33:51 +00002143
jjako08d331d2003-10-13 20:33:30 +00002144/* API: Send Delete PDP Context Request */
jjako2c381332003-10-21 19:09:53 +00002145int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2146 int teardown) {
jjako08d331d2003-10-13 20:33:30 +00002147 union gtp_packet packet;
jjako2c381332003-10-21 19:09:53 +00002148 int length = get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
jjako08d331d2003-10-13 20:33:30 +00002149 struct in_addr addr;
jjako2c381332003-10-21 19:09:53 +00002150 struct pdp_t *linked_pdp;
2151 struct pdp_t *secondary_pdp;
2152 int n;
2153 int count = 0;
2154
jjako52c24142002-12-16 13:33:51 +00002155 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2156 gsn->err_address++;
2157 gtp_err(LOG_ERR, __FILE__, __LINE__, "GSN address conversion failed");
2158 return EOF;
2159 }
jjako2c381332003-10-21 19:09:53 +00002160
2161 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2162 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown linked PDP context");
2163 return EOF;
2164 }
2165
2166 if (!teardown) {
2167 for (n=0; n< PDP_MAXNSAPI; n++)
2168 if (linked_pdp->secondary_tei[n]) count++;
2169 if (count <= 1) {
2170 gtp_err(LOG_ERR, __FILE__, __LINE__,
2171 "Must use teardown for last context");
2172 return EOF;
2173 }
2174 }
2175
jjako08d331d2003-10-13 20:33:30 +00002176 if (pdp->version == 1) {
2177 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
2178 pdp->nsapi);
jjako2c381332003-10-21 19:09:53 +00002179
2180 if (teardown)
2181 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2182 0xff);
jjako08d331d2003-10-13 20:33:30 +00002183 }
jjako52c24142002-12-16 13:33:51 +00002184
jjako2c381332003-10-21 19:09:53 +00002185 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
jjako52c24142002-12-16 13:33:51 +00002186
jjako2c381332003-10-21 19:09:53 +00002187 if (teardown) { /* Remove all contexts */
2188 for (n=0; n< PDP_MAXNSAPI; n++) {
2189 if (linked_pdp->secondary_tei[n]) {
2190 if (pdp_getgtp1(&secondary_pdp, linked_pdp->secondary_tei[n])) {
2191 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown secondary PDP context");
2192 return EOF;
2193 }
2194 if (linked_pdp != secondary_pdp) {
2195 if (gsn->cb_delete_context) gsn->cb_delete_context(secondary_pdp);
2196 pdp_freepdp(secondary_pdp);
2197 }
2198 }
2199 }
2200 if (gsn->cb_delete_context) gsn->cb_delete_context(linked_pdp);
2201 pdp_freepdp(linked_pdp);
2202 }
2203 else {
2204 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2205 if (pdp == linked_pdp) {
2206 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2207 linked_pdp->nodata = 1;
2208 }
2209 else
2210 pdp_freepdp(pdp);
2211 }
2212
2213 return 0;
2214}
jjako08d331d2003-10-13 20:33:30 +00002215
jjako52c24142002-12-16 13:33:51 +00002216/* Send Delete PDP Context Response */
2217int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002218 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002219 void *pack, unsigned len,
jjako2c381332003-10-21 19:09:53 +00002220 struct pdp_t *pdp, struct pdp_t *linked_pdp,
2221 uint8_t cause, int teardown)
jjako52c24142002-12-16 13:33:51 +00002222{
2223 union gtp_packet packet;
jjako2c381332003-10-21 19:09:53 +00002224 struct pdp_t *secondary_pdp;
jjako08d331d2003-10-13 20:33:30 +00002225 int length = get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
jjako2c381332003-10-21 19:09:53 +00002226 int n;
jjako52c24142002-12-16 13:33:51 +00002227
jjako08d331d2003-10-13 20:33:30 +00002228 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
jjako52c24142002-12-16 13:33:51 +00002229
jjako08d331d2003-10-13 20:33:30 +00002230 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
jjako2c381332003-10-21 19:09:53 +00002231 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002232
jjako2c381332003-10-21 19:09:53 +00002233 if (cause == GTPCAUSE_ACC_REQ) {
2234 if ((teardown) || (version == 0)) { /* Remove all contexts */
2235 for (n=0; n< PDP_MAXNSAPI; n++) {
2236 if (linked_pdp->secondary_tei[n]) {
2237 if (pdp_getgtp1(&secondary_pdp, linked_pdp->secondary_tei[n])) {
2238 gtp_err(LOG_ERR, __FILE__, __LINE__,
2239 "Unknown secondary PDP context");
2240 return EOF;
2241 }
2242 if (linked_pdp != secondary_pdp) {
2243 if (gsn->cb_delete_context) gsn->cb_delete_context(secondary_pdp);
2244 pdp_freepdp(secondary_pdp);
2245 }
2246 }
2247 }
2248 if (gsn->cb_delete_context) gsn->cb_delete_context(linked_pdp);
2249 pdp_freepdp(linked_pdp);
2250 }
2251 else { /* Remove only current context */
2252 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2253 if (pdp == linked_pdp) {
2254 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2255 linked_pdp->nodata = 1;
2256 }
2257 else
2258 pdp_freepdp(pdp);
2259 }
2260 } /* if (cause == GTPCAUSE_ACC_REQ) */
jjako52c24142002-12-16 13:33:51 +00002261
jjako08d331d2003-10-13 20:33:30 +00002262 return 0;
jjako52c24142002-12-16 13:33:51 +00002263}
2264
2265/* Handle Delete PDP Context Request */
2266int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002267 struct sockaddr_in *peer, int fd,
2268 void *pack, unsigned len) {
jjako2c381332003-10-21 19:09:53 +00002269 struct pdp_t *pdp = NULL;
2270 struct pdp_t *linked_pdp = NULL;
jjako52c24142002-12-16 13:33:51 +00002271 union gtpie_member* ie[GTPIE_SIZE];
jjako08d331d2003-10-13 20:33:30 +00002272
2273 uint16_t seq = get_seq(pack);
2274 int hlen = get_hlen(pack);
jjako52c24142002-12-16 13:33:51 +00002275
jjako08d331d2003-10-13 20:33:30 +00002276 uint8_t nsapi;
jjako2c381332003-10-21 19:09:53 +00002277 uint8_t teardown = 0;
2278 int n;
2279 int count = 0;
2280
jjako52c24142002-12-16 13:33:51 +00002281 /* Is this a dublicate ? */
jjako08d331d2003-10-13 20:33:30 +00002282 if(!gtp_dublicate(gsn, version, peer, seq)) {
2283 return 0; /* We allready send off response once */
jjako52c24142002-12-16 13:33:51 +00002284 }
2285
jjako2c381332003-10-21 19:09:53 +00002286 /* Find the linked context in question */
2287 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
jjako52c24142002-12-16 13:33:51 +00002288 gsn->err_unknownpdp++;
2289 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2290 "Unknown PDP context");
jjako2c381332003-10-21 19:09:53 +00002291 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2292 GTPCAUSE_NON_EXIST, teardown);
jjako52c24142002-12-16 13:33:51 +00002293 }
jjako2c381332003-10-21 19:09:53 +00002294
2295 /* If version 0 this is also the secondary context */
2296 if (version == 0)
2297 pdp = linked_pdp;
jjako52c24142002-12-16 13:33:51 +00002298
2299 /* Decode information elements */
jjako08d331d2003-10-13 20:33:30 +00002300 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
jjako52c24142002-12-16 13:33:51 +00002301 gsn->invalid++;
2302 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2303 "Invalid message format");
2304 if (0 == version)
2305 return EOF;
2306 else
jjako2c381332003-10-21 19:09:53 +00002307 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2308 GTPCAUSE_INVALID_MESSAGE, teardown);
jjako52c24142002-12-16 13:33:51 +00002309 }
jjako2c381332003-10-21 19:09:53 +00002310
jjako08d331d2003-10-13 20:33:30 +00002311 if (version == 1) {
2312 /* NSAPI (mandatory) */
2313 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2314 gsn->missing++;
2315 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2316 "Missing mandatory information field");
jjako2c381332003-10-21 19:09:53 +00002317 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2318 GTPCAUSE_MAN_IE_MISSING, teardown);
jjako08d331d2003-10-13 20:33:30 +00002319 }
jjako2c381332003-10-21 19:09:53 +00002320
2321 /* Find the context in question */
2322 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2323 gsn->err_unknownpdp++;
2324 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2325 "Unknown PDP context");
2326 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2327 GTPCAUSE_NON_EXIST, teardown);
2328 }
jjako08d331d2003-10-13 20:33:30 +00002329
2330 /* Teardown (conditional) */
jjako2c381332003-10-21 19:09:53 +00002331 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2332
2333 if (!teardown) {
2334 for (n=0; n< PDP_MAXNSAPI; n++)
2335 if (linked_pdp->secondary_tei[n]) count++;
2336 if (count <= 1) {
2337 return 0; /* 29.060 7.3.5 Ignore message */
2338 }
jjako08d331d2003-10-13 20:33:30 +00002339 }
2340 }
jjako2c381332003-10-21 19:09:53 +00002341
2342 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2343 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
jjako52c24142002-12-16 13:33:51 +00002344}
2345
2346
2347/* Handle Delete PDP Context Response */
2348int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
2349 struct sockaddr_in *peer,
2350 void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +00002351 union gtpie_member *ie[GTPIE_SIZE];
2352 uint8_t cause;
jjako08d331d2003-10-13 20:33:30 +00002353 void *cbp = NULL;
jjako52c24142002-12-16 13:33:51 +00002354 uint8_t type = 0;
jjako08d331d2003-10-13 20:33:30 +00002355 int hlen = get_hlen(pack);
2356
jjako52c24142002-12-16 13:33:51 +00002357 /* Remove packet from queue */
jjako08d331d2003-10-13 20:33:30 +00002358 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
jjako52c24142002-12-16 13:33:51 +00002359
jjako52c24142002-12-16 13:33:51 +00002360 /* Decode information elements */
jjako08d331d2003-10-13 20:33:30 +00002361 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
jjako52c24142002-12-16 13:33:51 +00002362 gsn->invalid++;
2363 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2364 "Invalid message format");
jjako2c381332003-10-21 19:09:53 +00002365 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +00002366 return EOF;
2367 }
2368
jjako08d331d2003-10-13 20:33:30 +00002369 /* Extract cause value (mandatory) */
jjako52c24142002-12-16 13:33:51 +00002370 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2371 gsn->missing++;
2372 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2373 "Missing mandatory information field");
jjako2c381332003-10-21 19:09:53 +00002374 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +00002375 return EOF;
2376 }
2377
jjako2c381332003-10-21 19:09:53 +00002378 /* Check the cause value (again) */
2379 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
jjako52c24142002-12-16 13:33:51 +00002380 gsn->err_cause++;
2381 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2382 "Unexpected cause value received: %d", cause);
jjako2c381332003-10-21 19:09:53 +00002383 if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
2384 return EOF;
jjako52c24142002-12-16 13:33:51 +00002385 }
jjako2c381332003-10-21 19:09:53 +00002386
jjako08d331d2003-10-13 20:33:30 +00002387 /* Callback function to notify application */
jjako2c381332003-10-21 19:09:53 +00002388 if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
jjako52c24142002-12-16 13:33:51 +00002389
2390 return 0;
2391}
2392
2393/* Send Error Indication (response to a GPDU message */
2394int gtp_error_ind_resp(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002395 struct sockaddr_in *peer, int fd,
jjako52c24142002-12-16 13:33:51 +00002396 void *pack, unsigned len)
2397{
2398 union gtp_packet packet;
jjako08d331d2003-10-13 20:33:30 +00002399 int length = get_default_gtp(version, GTP_ERROR, &packet);
jjako52c24142002-12-16 13:33:51 +00002400
jjako08d331d2003-10-13 20:33:30 +00002401 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2402 get_seq(pack), get_tid(pack));
jjako52c24142002-12-16 13:33:51 +00002403}
2404
2405/* Handle Error Indication */
2406int gtp_error_ind_conf(struct gsn_t *gsn, int version,
2407 struct sockaddr_in *peer,
2408 void *pack, unsigned len) {
2409 struct pdp_t *pdp;
2410
2411 /* Find the context in question */
2412 if (pdp_tidget(&pdp, ((union gtp_packet*)pack)->gtp0.h.tid)) {
2413 gsn->err_unknownpdp++;
2414 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2415 "Unknown PDP context");
2416 return EOF;
2417 }
2418
2419 gsn->err_unknownpdp++; /* TODO: Change counter */
2420 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2421 "Received Error Indication");
2422
2423 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2424 pdp_freepdp(pdp);
2425 return 0;
2426}
2427
2428int gtp_gpdu_ind(struct gsn_t *gsn, int version,
jjako08d331d2003-10-13 20:33:30 +00002429 struct sockaddr_in *peer, int fd,
2430 void *pack, unsigned len) {
2431
2432 int hlen = GTP1_HEADER_SIZE_SHORT;
jjako52c24142002-12-16 13:33:51 +00002433
2434 /* Need to include code to verify packet src and dest addresses */
2435 struct pdp_t *pdp;
jjako1db1c812003-07-06 20:53:57 +00002436
jjako08d331d2003-10-13 20:33:30 +00002437 if (version == 0) {
2438 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet*)pack)->gtp0.h.flow))) {
2439 gsn->err_unknownpdp++;
2440 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2441 "Unknown PDP context");
2442 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2443 }
2444 hlen = GTP0_HEADER_SIZE;
2445 }
2446 else if (version == 1) {
2447 if (pdp_getgtp1(&pdp, ntoh32(((union gtp_packet*)pack)->gtp1l.h.tei))) {
2448 gsn->err_unknownpdp++;
2449 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2450 "Unknown PDP context");
2451 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2452 }
2453
2454 /* Is this a long or a short header ? */
2455 if (((union gtp_packet*)pack)->gtp1l.h.flags & 0x07)
2456 hlen = GTP1_HEADER_SIZE_LONG;
2457 else
2458 hlen = GTP1_HEADER_SIZE_SHORT;
2459 }
2460 else {
2461 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2462 "Unknown version");
2463 }
2464
jjako1db1c812003-07-06 20:53:57 +00002465 /* If the GPDU was not from the peer GSN tell him to delete context */
2466 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2467 gsn->err_unknownpdp++;
2468 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2469 "Unknown PDP context");
jjako08d331d2003-10-13 20:33:30 +00002470 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
jjako1db1c812003-07-06 20:53:57 +00002471 }
jjako08d331d2003-10-13 20:33:30 +00002472
jjako52c24142002-12-16 13:33:51 +00002473 /* Callback function */
jjako08d331d2003-10-13 20:33:30 +00002474 if (gsn->cb_data_ind !=0)
2475 return gsn->cb_data_ind(pdp, pack+hlen, len-hlen);
jjako52c24142002-12-16 13:33:51 +00002476
2477 return 0;
2478}
2479
2480
jjako08d331d2003-10-13 20:33:30 +00002481
jjako52c24142002-12-16 13:33:51 +00002482/* Receives GTP packet and sends off for further processing
2483 * Function will check the validity of the header. If the header
2484 * is not valid the packet is either dropped or a version not
2485 * supported is returned to the peer.
2486 * TODO: Need to decide on return values! */
jjako08d331d2003-10-13 20:33:30 +00002487int gtp_decaps0(struct gsn_t *gsn)
jjako52c24142002-12-16 13:33:51 +00002488{
jjako2c381332003-10-21 19:09:53 +00002489 unsigned char buffer[PACKET_MAX];
jjako52c24142002-12-16 13:33:51 +00002490 struct sockaddr_in peer;
2491 int peerlen;
jjako08d331d2003-10-13 20:33:30 +00002492 int status;
jjako52c24142002-12-16 13:33:51 +00002493 struct gtp0_header *pheader;
2494 int version = 0; /* GTP version should be determined from header!*/
jjako08d331d2003-10-13 20:33:30 +00002495 int fd = gsn->fd0;
jjako52c24142002-12-16 13:33:51 +00002496
jjakoa7cd2492003-04-11 09:40:12 +00002497 /* TODO: Need strategy of userspace buffering and blocking */
2498 /* Currently read is non-blocking and send is blocking. */
2499 /* This means that the program have to wait for busy send calls...*/
jjako52c24142002-12-16 13:33:51 +00002500
jjakoa7cd2492003-04-11 09:40:12 +00002501 while (1) { /* Loop until no more to read */
jjako08d331d2003-10-13 20:33:30 +00002502 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
jjakoa7cd2492003-04-11 09:40:12 +00002503 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2504 return -1;
2505 }
2506 peerlen = sizeof(peer);
2507 if ((status =
jjako08d331d2003-10-13 20:33:30 +00002508 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
jjakoa7cd2492003-04-11 09:40:12 +00002509 (struct sockaddr *) &peer, &peerlen)) < 0 ) {
jjako08d331d2003-10-13 20:33:30 +00002510 if (errno == EAGAIN) return 0;
jjakoa7cd2492003-04-11 09:40:12 +00002511 gsn->err_readfrom++;
jjako08d331d2003-10-13 20:33:30 +00002512 gtp_err(LOG_ERR, __FILE__, __LINE__, "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s", gsn->fd0, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
jjakoa7cd2492003-04-11 09:40:12 +00002513 return -1;
2514 }
jjako52c24142002-12-16 13:33:51 +00002515
jjakoa7cd2492003-04-11 09:40:12 +00002516 /* Need at least 1 byte in order to check version */
2517 if (status < (1)) {
2518 gsn->empty++;
2519 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2520 "Discarding packet - too small");
2521 continue;
2522 }
2523
jjako08d331d2003-10-13 20:33:30 +00002524 pheader = (struct gtp0_header *) (buffer);
jjakoa7cd2492003-04-11 09:40:12 +00002525
jjako08d331d2003-10-13 20:33:30 +00002526 /* Version should be gtp0 (or earlier) */
2527 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2528 /* GTP 0 messages. If other version message is received we reply that we */
2529 /* only support version 0, implying that this is the only version */
2530 /* supported on this port */
jjakoa7cd2492003-04-11 09:40:12 +00002531 if (((pheader->flags & 0xe0) > 0x00)) {
2532 gsn->unsup++;
2533 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2534 "Unsupported GTP version");
jjako08d331d2003-10-13 20:33:30 +00002535 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
jjakoa7cd2492003-04-11 09:40:12 +00002536 continue;
2537 }
2538
2539 /* Check length of gtp0 packet */
jjako08d331d2003-10-13 20:33:30 +00002540 if (status < GTP0_HEADER_SIZE) {
jjakoa7cd2492003-04-11 09:40:12 +00002541 gsn->tooshort++;
2542 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2543 "GTP0 packet too short");
2544 continue; /* Silently discard 29.60: 11.1.2 */
2545 }
jjako1db1c812003-07-06 20:53:57 +00002546
jjako08d331d2003-10-13 20:33:30 +00002547 /* Check packet length field versus length of packet */
2548 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2549 gsn->tooshort++;
2550 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2551 "GTP packet length field does not match actual length");
2552 continue; /* Silently discard */
2553 }
2554
2555 if ((gsn->mode == GTP_MODE_GGSN) &&
2556 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2557 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2558 (pheader->type == GTP_DELETE_PDP_RSP))) {
2559 gsn->unexpect++;
2560 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2561 "Unexpected GTP Signalling Message");
2562 continue; /* Silently discard 29.60: 11.1.4 */
2563 }
2564
2565 if ((gsn->mode == GTP_MODE_SGSN) &&
2566 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2567 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2568 (pheader->type == GTP_DELETE_PDP_REQ))) {
2569 gsn->unexpect++;
2570 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2571 "Unexpected GTP Signalling Message");
2572 continue; /* Silently discard 29.60: 11.1.4 */
2573 }
2574
2575 switch (pheader->type) {
2576 case GTP_ECHO_REQ:
2577 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2578 break;
2579 case GTP_ECHO_RSP:
2580 gtp_echo_conf(gsn, version, &peer, buffer, status);
2581 break;
2582 case GTP_NOT_SUPPORTED:
2583 gtp_unsup_ind(gsn, &peer, buffer, status);
2584 break;
2585 case GTP_CREATE_PDP_REQ:
2586 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer, status);
2587 break;
2588 case GTP_CREATE_PDP_RSP:
2589 gtp_create_pdp_conf(gsn, version, &peer, buffer, status);
2590 break;
2591 case GTP_UPDATE_PDP_REQ:
2592 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer, status);
2593 break;
2594 case GTP_UPDATE_PDP_RSP:
2595 gtp_update_pdp_conf(gsn, version, &peer, buffer, status);
2596 break;
2597 case GTP_DELETE_PDP_REQ:
2598 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer, status);
2599 break;
2600 case GTP_DELETE_PDP_RSP:
2601 gtp_delete_pdp_conf(gsn, version, &peer, buffer, status);
2602 break;
2603 case GTP_ERROR:
2604 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2605 break;
2606 case GTP_GPDU:
2607 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2608 break;
2609 default:
2610 gsn->unknown++;
2611 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2612 "Unknown GTP message type received");
2613 break;
2614 }
2615 }
2616}
2617
2618
2619int gtp_decaps1c(struct gsn_t *gsn)
2620{
jjako2c381332003-10-21 19:09:53 +00002621 unsigned char buffer[PACKET_MAX];
jjako08d331d2003-10-13 20:33:30 +00002622 struct sockaddr_in peer;
2623 int peerlen;
2624 int status;
2625 struct gtp1_header_short *pheader;
jjako2c381332003-10-21 19:09:53 +00002626 int version = 1; /* TODO GTP version should be determined from header!*/
jjako08d331d2003-10-13 20:33:30 +00002627 int fd = gsn->fd1c;
2628
2629 /* TODO: Need strategy of userspace buffering and blocking */
2630 /* Currently read is non-blocking and send is blocking. */
2631 /* This means that the program have to wait for busy send calls...*/
2632
2633 while (1) { /* Loop until no more to read */
jjako2c381332003-10-21 19:09:53 +00002634 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
jjako08d331d2003-10-13 20:33:30 +00002635 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2636 return -1;
2637 }
2638 peerlen = sizeof(peer);
2639 if ((status =
jjako2c381332003-10-21 19:09:53 +00002640 recvfrom(fd, buffer, sizeof(buffer), 0,
jjako08d331d2003-10-13 20:33:30 +00002641 (struct sockaddr *) &peer, &peerlen)) < 0 ) {
2642 if (errno == EAGAIN) return 0;
2643 gsn->err_readfrom++;
jjako2c381332003-10-21 19:09:53 +00002644 gtp_err(LOG_ERR, __FILE__, __LINE__, "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s", fd, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
jjako08d331d2003-10-13 20:33:30 +00002645 return -1;
2646 }
2647
2648 /* Need at least 1 byte in order to check version */
2649 if (status < (1)) {
2650 gsn->empty++;
2651 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2652 "Discarding packet - too small");
2653 continue;
2654 }
2655
2656 pheader = (struct gtp1_header_short *) (buffer);
2657
2658 /* Version must be no larger than GTP 1 */
2659 if (((pheader->flags & 0xe0) > 0x20)) {
2660 gsn->unsup++;
2661 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2662 "Unsupported GTP version");
jjako2c381332003-10-21 19:09:53 +00002663 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2664 /*29.60: 11.1.1*/
jjako08d331d2003-10-13 20:33:30 +00002665 continue;
2666 }
2667
2668 /* Version must be at least GTP 1 */
2669 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2670 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2671 /* the message */
2672 if (((pheader->flags & 0xe0) < 0x20)) {
2673 gsn->unsup++;
2674 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2675 "Unsupported GTP version");
2676 continue;
2677 }
2678
2679 /* Check packet flag field */
2680 if (((pheader->flags & 0xf7) != 0x32)) {
2681 gsn->unsup++;
2682 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2683 "Unsupported packet flag");
2684 continue;
2685 }
2686
2687 /* Check length of packet */
2688 if (status < GTP1_HEADER_SIZE_LONG) {
2689 gsn->tooshort++;
2690 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2691 "GTP packet too short");
2692 continue; /* Silently discard 29.60: 11.1.2 */
2693 }
2694
2695 /* Check packet length field versus length of packet */
2696 if (status != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2697 gsn->tooshort++;
2698 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2699 "GTP packet length field does not match actual length");
2700 continue; /* Silently discard */
2701 }
2702
jjako2c381332003-10-21 19:09:53 +00002703 /* Check for extension headers */
2704 /* TODO: We really should cycle through the headers and determine */
2705 /* if any have the comprehension required flag set */
2706 if (((pheader->flags & 0x04) != 0x00)) {
2707 gsn->unsup++;
2708 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2709 "Unsupported extension header");
2710 gtp_extheader_req(gsn, version, &peer, fd, buffer, status);
2711
2712 continue;
2713 }
2714
jjako1db1c812003-07-06 20:53:57 +00002715 if ((gsn->mode == GTP_MODE_GGSN) &&
2716 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2717 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2718 (pheader->type == GTP_DELETE_PDP_RSP))) {
2719 gsn->unexpect++;
2720 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2721 "Unexpected GTP Signalling Message");
2722 continue; /* Silently discard 29.60: 11.1.4 */
2723 }
2724
2725 if ((gsn->mode == GTP_MODE_SGSN) &&
2726 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2727 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2728 (pheader->type == GTP_DELETE_PDP_REQ))) {
2729 gsn->unexpect++;
2730 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2731 "Unexpected GTP Signalling Message");
2732 continue; /* Silently discard 29.60: 11.1.4 */
2733 }
2734
jjakoa7cd2492003-04-11 09:40:12 +00002735 switch (pheader->type) {
2736 case GTP_ECHO_REQ:
jjako08d331d2003-10-13 20:33:30 +00002737 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002738 break;
2739 case GTP_ECHO_RSP:
jjako08d331d2003-10-13 20:33:30 +00002740 gtp_echo_conf(gsn, version, &peer, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002741 break;
2742 case GTP_NOT_SUPPORTED:
jjako08d331d2003-10-13 20:33:30 +00002743 gtp_unsup_ind(gsn, &peer, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002744 break;
jjako2c381332003-10-21 19:09:53 +00002745 case GTP_SUPP_EXT_HEADER:
2746 gtp_extheader_ind(gsn, &peer, buffer, status);
2747 break;
jjakoa7cd2492003-04-11 09:40:12 +00002748 case GTP_CREATE_PDP_REQ:
jjako08d331d2003-10-13 20:33:30 +00002749 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002750 break;
2751 case GTP_CREATE_PDP_RSP:
jjako08d331d2003-10-13 20:33:30 +00002752 gtp_create_pdp_conf(gsn, version, &peer, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002753 break;
2754 case GTP_UPDATE_PDP_REQ:
jjako08d331d2003-10-13 20:33:30 +00002755 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002756 break;
2757 case GTP_UPDATE_PDP_RSP:
jjako08d331d2003-10-13 20:33:30 +00002758 gtp_update_pdp_conf(gsn, version, &peer, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002759 break;
2760 case GTP_DELETE_PDP_REQ:
jjako08d331d2003-10-13 20:33:30 +00002761 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002762 break;
2763 case GTP_DELETE_PDP_RSP:
jjako08d331d2003-10-13 20:33:30 +00002764 gtp_delete_pdp_conf(gsn, version, &peer, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002765 break;
2766 case GTP_ERROR:
jjako08d331d2003-10-13 20:33:30 +00002767 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
jjakoa7cd2492003-04-11 09:40:12 +00002768 break;
2769 default:
jjako52c24142002-12-16 13:33:51 +00002770 gsn->unknown++;
2771 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2772 "Unknown GTP message type received");
jjakoa7cd2492003-04-11 09:40:12 +00002773 break;
jjako52c24142002-12-16 13:33:51 +00002774 }
2775 }
2776}
2777
jjako08d331d2003-10-13 20:33:30 +00002778int gtp_decaps1u(struct gsn_t *gsn)
2779{
jjako2c381332003-10-21 19:09:53 +00002780 unsigned char buffer[PACKET_MAX];
jjako08d331d2003-10-13 20:33:30 +00002781 struct sockaddr_in peer;
2782 int peerlen;
2783 int status;
2784 struct gtp1_header_short *pheader;
2785 int version = 1; /* GTP version should be determined from header!*/
2786 int fd = gsn->fd1u;
2787
2788 /* TODO: Need strategy of userspace buffering and blocking */
2789 /* Currently read is non-blocking and send is blocking. */
2790 /* This means that the program have to wait for busy send calls...*/
2791
2792 while (1) { /* Loop until no more to read */
2793 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
2794 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2795 return -1;
2796 }
2797 peerlen = sizeof(peer);
2798 if ((status =
2799 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
2800 (struct sockaddr *) &peer, &peerlen)) < 0 ) {
2801 if (errno == EAGAIN) return 0;
2802 gsn->err_readfrom++;
2803 gtp_err(LOG_ERR, __FILE__, __LINE__, "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s", gsn->fd1u, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
2804 return -1;
2805 }
2806
2807 /* Need at least 1 byte in order to check version */
2808 if (status < (1)) {
2809 gsn->empty++;
2810 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2811 "Discarding packet - too small");
2812 continue;
2813 }
2814
2815 pheader = (struct gtp1_header_short *) (buffer);
2816
2817 /* Version must be no larger than GTP 1 */
2818 if (((pheader->flags & 0xe0) > 0x20)) {
2819 gsn->unsup++;
2820 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2821 "Unsupported GTP version");
2822 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status);/*29.60: 11.1.1*/
2823 continue;
2824 }
2825
2826 /* Version must be at least GTP 1 */
2827 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2828 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2829 /* the message */
2830 if (((pheader->flags & 0xe0) < 0x20)) {
2831 gsn->unsup++;
2832 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2833 "Unsupported GTP version");
2834 continue;
2835 }
2836
2837 /* Check packet flag field (allow both with and without sequence number)*/
2838 if (((pheader->flags & 0xf5) != 0x30)) {
2839 gsn->unsup++;
2840 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2841 "Unsupported packet flag");
2842 continue;
2843 }
2844
2845 /* Check length of packet */
2846 if (status < GTP1_HEADER_SIZE_SHORT) {
2847 gsn->tooshort++;
2848 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2849 "GTP packet too short");
2850 continue; /* Silently discard 29.60: 11.1.2 */
2851 }
2852
2853 /* Check packet length field versus length of packet */
2854 if (status != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2855 gsn->tooshort++;
2856 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2857 "GTP packet length field does not match actual length");
2858 continue; /* Silently discard */
2859 }
jjako2c381332003-10-21 19:09:53 +00002860
2861 /* Check for extension headers */
2862 /* TODO: We really should cycle through the headers and determine */
2863 /* if any have the comprehension required flag set */
2864 if (((pheader->flags & 0x04) != 0x00)) {
2865 gsn->unsup++;
2866 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2867 "Unsupported extension header");
2868 gtp_extheader_req(gsn, version, &peer, fd, buffer, status);
2869
2870 continue;
2871 }
jjako08d331d2003-10-13 20:33:30 +00002872
2873 switch (pheader->type) {
2874 case GTP_ECHO_REQ:
2875 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2876 break;
2877 case GTP_ECHO_RSP:
2878 gtp_echo_conf(gsn, version, &peer, buffer, status);
2879 break;
jjako2c381332003-10-21 19:09:53 +00002880 case GTP_SUPP_EXT_HEADER:
2881 gtp_extheader_ind(gsn, &peer, buffer, status);
2882 break;
jjako08d331d2003-10-13 20:33:30 +00002883 case GTP_ERROR:
2884 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2885 break;
2886 /* Supported header extensions */
2887 case GTP_GPDU:
2888 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2889 break;
2890 default:
2891 gsn->unknown++;
2892 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2893 "Unknown GTP message type received");
2894 break;
2895 }
2896 }
2897}
2898
2899int gtp_data_req(struct gsn_t *gsn, struct pdp_t* pdp,
jjako52c24142002-12-16 13:33:51 +00002900 void *pack, unsigned len)
2901{
2902 union gtp_packet packet;
2903 struct sockaddr_in addr;
jjako08d331d2003-10-13 20:33:30 +00002904 int fd;
2905 int length;
jjako52c24142002-12-16 13:33:51 +00002906
2907 memset(&addr, 0, sizeof(addr));
2908 addr.sin_family = AF_INET;
jjako52c24142002-12-16 13:33:51 +00002909 memcpy(&addr.sin_addr, pdp->gsnru.v,pdp->gsnru.l); /* TODO range check */
jjako52c24142002-12-16 13:33:51 +00002910
jjako08d331d2003-10-13 20:33:30 +00002911 if (pdp->version == 0) {
2912
2913 length = GTP0_HEADER_SIZE+len;
2914 addr.sin_port = htons(GTP0_PORT);
2915 fd = gsn->fd0;
2916
2917 get_default_gtp(0, GTP_GPDU, &packet);
2918 packet.gtp0.h.length = hton16(len);
2919 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
2920 packet.gtp0.h.flow = hton16(pdp->flru);
2921 packet.gtp0.h.tid = (pdp->imsi & 0x0fffffffffffffff) + ((uint64_t)pdp->nsapi << 60);
jjako52c24142002-12-16 13:33:51 +00002922
jjako08d331d2003-10-13 20:33:30 +00002923 if (len > sizeof (union gtp_packet) - sizeof(struct gtp0_header)) {
2924 gsn->err_memcpy++;
2925 gtp_err(LOG_ERR, __FILE__, __LINE__,
2926 "Memcpy failed");
2927 return EOF;
jjako52c24142002-12-16 13:33:51 +00002928 }
jjako08d331d2003-10-13 20:33:30 +00002929 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
2930 }
2931 else if (pdp->version == 1) {
2932
2933 length = GTP1_HEADER_SIZE_LONG+len;
2934 addr.sin_port = htons(GTP1U_PORT);
2935 fd = gsn->fd1u;
jjako52c24142002-12-16 13:33:51 +00002936
jjako08d331d2003-10-13 20:33:30 +00002937 get_default_gtp(1, GTP_GPDU, &packet);
2938 packet.gtp1l.h.length = hton16(len-GTP1_HEADER_SIZE_SHORT+
2939 GTP1_HEADER_SIZE_LONG);
2940 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
jjako2c381332003-10-21 19:09:53 +00002941 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
jjako08d331d2003-10-13 20:33:30 +00002942
2943 if (len > sizeof (union gtp_packet) - sizeof(struct gtp1_header_long)) {
2944 gsn->err_memcpy++;
2945 gtp_err(LOG_ERR, __FILE__, __LINE__,
2946 "Memcpy failed");
2947 return EOF;
2948 }
2949 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
2950 }
2951 else {
2952 gtp_err(LOG_ERR, __FILE__, __LINE__,
2953 "Unknown version");
2954 return EOF;
2955 }
2956
2957 if (fcntl(fd, F_SETFL, 0)) {
jjakoa7cd2492003-04-11 09:40:12 +00002958 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2959 return -1;
2960 }
2961
jjako08d331d2003-10-13 20:33:30 +00002962 if (sendto(fd, &packet, length, 0,
jjako52c24142002-12-16 13:33:51 +00002963 (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2964 gsn->err_sendto++;
jjako08d331d2003-10-13 20:33:30 +00002965 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, GTP0_HEADER_SIZE+len, strerror(errno));
jjako52c24142002-12-16 13:33:51 +00002966 return EOF;
2967 }
2968 return 0;
2969}
2970
2971
2972/* ***********************************************************
2973 * Conversion functions
2974 *************************************************************/
2975
2976int char2ul_t(char* src, struct ul_t dst) {
2977 dst.l = strlen(src)+1;
2978 dst.v = malloc(dst.l);
2979 dst.v[0] = dst.l - 1;
2980 memcpy(&dst.v[1], src, dst.v[0]);
2981 return 0;
2982}
2983
2984/* ***********************************************************
2985 * IP address conversion functions
2986 * There exist several types of address representations:
2987 * - eua: End User Address. (29.060, 7.7.27, message type 128)
2988 * Used for signalling address to mobile station. Supports IPv4
2989 * IPv6 x.25 etc. etc.
2990 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
2991 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
2992 * - in_addr: IPv4 address struct.
2993 * - sockaddr_in: Socket API representation of IP address and
2994 * port number.
2995 *************************************************************/
2996
2997int ipv42eua(struct ul66_t *eua, struct in_addr *src) {
2998 eua->v[0] = 0xf1; /* IETF */
2999 eua->v[1] = 0x21; /* IPv4 */
3000 if (src) {
3001 eua->l = 6;
3002 memcpy(&eua->v[2], src, 4);
3003 }
3004 else
3005 {
3006 eua->l = 2;
3007 }
3008 return 0;
3009}
3010
3011int eua2ipv4(struct in_addr *dst, struct ul66_t *eua) {
3012 if ((eua->l != 6) ||
3013 (eua->v[0] != 0xf1) ||
3014 (eua->v[1] = 0x21))
3015 return -1; /* Not IPv4 address*/
3016 memcpy(dst, &eua->v[2], 4);
3017 return 0;
3018}
3019
3020int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna) {
3021 memset(dst, 0, sizeof(struct in_addr));
3022 if (gsna->l != 4) return EOF; /* Return if not IPv4 */
3023 memcpy(dst, gsna->v, gsna->l);
3024 return 0;
3025}
3026
3027int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src) {
3028 memset(gsna, 0, sizeof(struct ul16_t));
3029 gsna->l = 4;
3030 memcpy(gsna->v, src, gsna->l);
3031 return 0;
3032}
3033