sgsnemu: delete pdp context - teardown must be before NSAPI
[openggsn.git] / gtp / gtp.c
blob6d567ffa0847283db09221657957dc459ceef7b3
1 /*
2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002, 2003, 2004 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 *
13 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
14 * tunnels in the same program.
16 * TODO:
17 * - Do we need to handle fragmentation?
21 #ifdef __linux__
22 #define _GNU_SOURCE 1
23 #endif
25 #include "../config.h"
26 #ifdef HAVE_STDINT_H
27 #include <stdint.h>
28 #endif
30 #include <syslog.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <stdlib.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #include <sys/stat.h>
40 #include <time.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <fcntl.h>
46 #include <arpa/inet.h>
48 /* #include <stdint.h> ISO C99 types */
50 #include "pdp.h"
51 #include "gtp.h"
52 #include "gtpie.h"
53 #include "queue.h"
56 /* Error reporting functions */
58 void gtp_err(int priority, char *filename, int linenum, char *fmt, ...) {
59 va_list args;
60 char buf[ERRMSG_SIZE];
62 va_start(args, fmt);
63 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
64 va_end(args);
65 buf[ERRMSG_SIZE-1] = 0;
66 syslog(priority, "%s: %d: %s", filename, linenum, buf);
69 void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
70 void *pack, unsigned len, char *fmt, ...) {
72 va_list args;
73 char buf[ERRMSG_SIZE];
74 char buf2[ERRMSG_SIZE];
75 unsigned int n;
76 int pos;
78 va_start(args, fmt);
79 vsnprintf(buf, ERRMSG_SIZE, fmt, args);
80 va_end(args);
81 buf[ERRMSG_SIZE-1] = 0;
83 snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
84 inet_ntoa(peer->sin_addr),
85 ntohs(peer->sin_port),
86 len);
87 buf2[ERRMSG_SIZE-1] = 0;
88 pos = strlen(buf2);
89 for(n=0; n<len; n++) {
90 if ((pos+4)<ERRMSG_SIZE) {
91 sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
92 pos += 3;
95 buf2[pos] = 0;
97 syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
104 /* API Functions */
106 const char* gtp_version()
108 return VERSION;
111 /* gtp_new */
112 /* gtp_free */
114 int gtp_newpdp(struct gsn_t* gsn, struct pdp_t **pdp,
115 uint64_t imsi, uint8_t nsapi) {
116 return pdp_newpdp(pdp, imsi, nsapi, NULL);
119 int gtp_freepdp(struct gsn_t* gsn, struct pdp_t *pdp) {
120 return pdp_freepdp(pdp);
123 /* gtp_gpdu */
125 extern int gtp_fd(struct gsn_t *gsn) {
126 return gsn->fd0;
129 /* gtp_decaps */
130 /* gtp_retrans */
131 /* gtp_retranstimeout */
134 int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
135 int (*cb) (struct sockaddr_in *peer)) {
136 gsn->cb_unsup_ind = cb;
137 return 0;
140 int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
141 int (*cb) (struct sockaddr_in *peer)) {
142 gsn->cb_extheader_ind = cb;
143 return 0;
147 /* API: Initialise delete context callback */
148 /* Called whenever a pdp context is deleted for any reason */
149 int gtp_set_cb_delete_context(struct gsn_t *gsn,
150 int (*cb) (struct pdp_t* pdp))
152 gsn->cb_delete_context = cb;
153 return 0;
156 int gtp_set_cb_conf(struct gsn_t *gsn,
157 int (*cb) (int type, int cause,
158 struct pdp_t* pdp, void *cbp)) {
159 gsn->cb_conf = cb;
160 return 0;
163 extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
164 int (*cb_data_ind) (struct pdp_t* pdp,
165 void* pack,
166 unsigned len))
168 gsn->cb_data_ind = cb_data_ind;
169 return 0;
173 * get_default_gtp()
174 * Generate a GPRS Tunneling Protocol signalling packet header, depending
175 * on GTP version and message type. pdp is used for teid/flow label.
176 * *packet must be allocated by the calling function, and be large enough
177 * to hold the packet header.
178 * returns the length of the header. 0 on error.
180 static unsigned int get_default_gtp(int version, uint8_t type, void *packet) {
181 struct gtp0_header *gtp0_default = (struct gtp0_header*) packet;
182 struct gtp1_header_long *gtp1_default = (struct gtp1_header_long*) packet;
183 switch (version) {
184 case 0:
185 /* Initialise "standard" GTP0 header */
186 memset(gtp0_default, 0, sizeof(struct gtp0_header));
187 gtp0_default->flags=0x1e;
188 gtp0_default->type=hton8(type);
189 gtp0_default->spare1=0xff;
190 gtp0_default->spare2=0xff;
191 gtp0_default->spare3=0xff;
192 gtp0_default->number=0xff;
193 return GTP0_HEADER_SIZE;
194 case 1:
195 /* Initialise "standard" GTP1 header */
196 /* 29.060: 8.2: S=1 and PN=0 */
197 /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
198 /* and Supported Extension Headers Notification, the S field shall be */
199 /* set to 1 */
200 /* Currently extension headers are not supported */
201 memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
202 gtp1_default->flags=0x32; /* No extension, enable sequence, no N-PDU */
203 gtp1_default->type=hton8(type);
204 return GTP1_HEADER_SIZE_LONG;
205 default:
206 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown GTP packet version");
207 return 0;
212 * get_seq()
213 * Get sequence number of a packet.
214 * Returns 0 on error
216 static uint16_t get_seq(void *pack) {
217 union gtp_packet *packet = (union gtp_packet *) pack;
219 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
220 return ntoh16(packet->gtp0.h.seq);
222 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
223 return ntoh16(packet->gtp1l.h.seq);
224 } else {
225 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
226 return 0;
231 * get_tid()
232 * Get tunnel identifier of a packet.
233 * Returns 0 on error
235 static uint64_t get_tid(void *pack) {
236 union gtp_packet *packet = (union gtp_packet *) pack;
238 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
239 return packet->gtp0.h.tid;
241 return 0;
245 * get_hlen()
246 * Get the header length of a packet.
247 * Returns 0 on error
249 static uint16_t get_hlen(void *pack) {
250 union gtp_packet *packet = (union gtp_packet *) pack;
252 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
253 return GTP0_HEADER_SIZE;
255 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
256 return GTP1_HEADER_SIZE_LONG;
258 else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
259 return GTP1_HEADER_SIZE_SHORT;
260 } else {
261 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
262 return 0;
267 * get_tei()
268 * Get the tunnel endpoint identifier (flow label) of a packet.
269 * Returns 0xffffffff on error.
271 static uint32_t get_tei(void *pack) {
272 union gtp_packet *packet = (union gtp_packet *) pack;
274 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
275 return ntoh16(packet->gtp0.h.flow);
277 else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
278 return ntoh32(packet->gtp1l.h.tei);
280 else {
281 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
282 return 0xffffffff;
287 int print_packet(void *packet, unsigned len)
289 unsigned int i;
290 printf("The packet looks like this (%d bytes):\n", len);
291 for( i=0; i<len; i++) {
292 printf("%02x ", (unsigned char)*(char *)(packet+i));
293 if (!((i+1)%16)) printf("\n");
295 printf("\n");
296 return 0;
299 char* snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
300 void *pack, unsigned len, char *buf, int size) {
301 unsigned int n;
302 int pos;
303 snprintf(buf, size, "Packet from %s:%u, length: %d, content:",
304 inet_ntoa(peer->sin_addr),
305 ntohs(peer->sin_port),
306 len);
307 buf[size-1] = 0;
308 pos = strlen(buf);
309 for(n=0; n<len; n++) {
310 if ((pos+4)<size) {
311 sprintf((buf+pos), " %02hhx", ((unsigned char*)pack)[n]);
312 pos += 3;
315 buf[pos] = 0;
316 return buf;
320 /* ***********************************************************
321 * Reliable delivery of signalling messages
323 * Sequence numbers are used for both signalling messages and
324 * data messages.
326 * For data messages each tunnel maintains a sequence counter,
327 * which is incremented by one each time a new data message
328 * is sent. The sequence number starts at (0) zero at tunnel
329 * establishment, and wraps around at 65535 (29.060 9.3.1.1
330 * and 09.60 8.1.1.1). The sequence numbers are either ignored,
331 * or can be used to check the validity of the message in the
332 * receiver, or for reordering af packets.
334 * For signalling messages the sequence number is used by
335 * signalling messages for which a response is defined. A response
336 * message should copy the sequence from the corresponding request
337 * message. The sequence number "unambiguously" identifies a request
338 * message within a given path, with a path being defined as a set of
339 * two endpoints (29.060 8.2, 29.060 7.6, 09.60 7.8). "All request
340 * messages shall be responded to, and all response messages associated
341 * with a certain request shall always include the same information"
343 * We take this to mean that the GSN transmitting a request is free to
344 * choose the sequence number, as long as it is unique within a given path.
345 * It means that we are allowed to count backwards, or roll over at 17
346 * if we prefer that. It also means that we can use the same counter for
347 * all paths. This has the advantage that the transmitted request sequence
348 * numbers are unique within each GSN, and also we dont have to mess around
349 * with path setup and teardown.
351 * If a response message is lost, the request will be retransmitted, and
352 * the receiving GSN will receive a "duplicated" request. The standard
353 * requires the receiving GSN to send a response, with the same information
354 * as in the original response. For most messages this happens automatically:
356 * Echo: Automatically dublicates the original response
357 * Create pdp context: The SGSN may send create context request even if
358 * a context allready exist (imsi+nsapi?). This means that the reply will
359 automatically dublicate the original response. It might however have
360 * side effects in the application which is asked twice to validate
361 * the login.
362 * Update pdp context: Automatically dublicates the original response???
363 * Delete pdp context. Automatically in gtp0, but in gtp1 will generate
364 * a nonexist reply message.
366 * The correct solution will be to make a queue containing response messages.
367 * This queue should be checked whenever a request is received. If the
368 * response is allready in the queue that response should be transmitted.
369 * It should be possible to find messages in this queue on the basis of
370 * the sequence number and peer GSN IP address (The sequense number is unique
371 * within each path). This need to be implemented by a hash table. Furthermore
372 * it should be possibly to delete messages based on a timeout. This can be
373 * achieved by means of a linked list. The timeout value need to be larger
374 * than T3-RESPONSE * N3-REQUESTS (recommended value 5). These timers are
375 * set in the peer GSN, so there is no way to know these parameters. On the
376 * other hand the timeout value need to be so small that we do not receive
377 * wraparound sequence numbere before the message is deleted. 60 seconds is
378 * probably not a bad choise.
380 * This queue however is first really needed from gtp1.
382 * gtp_req:
383 * Send off a signalling message with appropiate sequence
384 * number. Store packet in queue.
385 * gtp_conf:
386 * Remove an incoming confirmation from the queue
387 * gtp_resp:
388 * Send off a response to a request. Use the same sequence
389 * number in the response as in the request.
390 * gtp_notification:
391 * Send off a notification message. This is neither a request nor
392 * a response. Both TEI and SEQ are zero.
393 * gtp_retrans:
394 * Retransmit any outstanding packets which have exceeded
395 * a predefined timeout.
396 *************************************************************/
398 int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
399 union gtp_packet *packet, int len,
400 struct in_addr *inetaddr, void *cbp) {
401 struct sockaddr_in addr;
402 struct qmsg_t *qmsg;
403 int fd;
405 memset(&addr, 0, sizeof(addr));
406 addr.sin_family = AF_INET;
407 addr.sin_addr = *inetaddr;
408 #if defined(__FreeBSD__) || defined(__APPLE__)
409 addr.sin_len = sizeof(addr);
410 #endif
412 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
413 addr.sin_port = htons(GTP0_PORT);
414 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
415 packet->gtp0.h.seq = hton16(gsn->seq_next);
416 if (pdp)
417 packet->gtp0.h.tid = (pdp->imsi & 0x0fffffffffffffffull) +
418 ((uint64_t)pdp->nsapi << 60);
419 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
420 (packet->gtp0.h.type == GTP_ERROR)))
421 packet->gtp0.h.flow=hton16(pdp->flru);
422 else if (pdp)
423 packet->gtp0.h.flow=hton16(pdp->flrc);
424 fd = gsn->fd0;
426 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
427 addr.sin_port = htons(GTP1C_PORT);
428 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
429 packet->gtp1l.h.seq = hton16(gsn->seq_next);
430 if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
431 (packet->gtp1l.h.type == GTP_ERROR)))
432 packet->gtp1l.h.tei=hton32(pdp->teid_gn);
433 else if (pdp)
434 packet->gtp1l.h.tei=hton32(pdp->teic_gn);
435 fd = gsn->fd1c;
436 } else {
437 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
438 return -1;
441 if (sendto(fd, packet, len, 0,
442 (struct sockaddr *) &addr, sizeof(addr)) < 0) {
443 gsn->err_sendto++;
444 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
445 return -1;
448 /* Use new queue structure */
449 if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
450 gsn->err_queuefull++;
451 gtp_err(LOG_ERR, __FILE__, __LINE__, "Retransmit queue is full");
453 else {
454 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
455 qmsg->l = len;
456 qmsg->timeout = time(NULL) + 3; /* When to timeout */
457 qmsg->retrans = 0; /* No retransmissions so far */
458 qmsg->cbp = cbp;
459 qmsg->type = ntoh8(packet->gtp0.h.type);
460 qmsg->fd = fd;
462 gsn->seq_next++; /* Count up this time */
463 return 0;
466 /* gtp_conf
467 * Remove signalling packet from retransmission queue.
468 * return 0 on success, EOF if packet was not found */
470 int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
471 union gtp_packet *packet, int len, uint8_t *type, void **cbp) {
473 uint16_t seq;
475 if ((packet->gtp0.h.flags & 0xe0) == 0x00)
476 seq = ntoh16(packet->gtp0.h.seq);
477 else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
478 seq = ntoh16(packet->gtp1l.h.seq);
479 else {
480 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
481 "Unknown GTP packet version");
482 return EOF;
485 if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
486 gsn->err_seq++;
487 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
488 "Confirmation packet not found in queue");
489 return EOF;
492 return 0;
495 int gtp_retrans(struct gsn_t *gsn) {
496 /* Retransmit any outstanding packets */
497 /* Remove from queue if maxretrans exceeded */
498 time_t now;
499 struct qmsg_t *qmsg;
500 now = time(NULL);
501 /*printf("Retrans: New beginning %d\n", (int) now);*/
503 while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
504 (qmsg->timeout <= now)) {
505 /*printf("Retrans timeout found: %d\n", (int) time(NULL));*/
506 if (qmsg->retrans > 3) { /* To many retrans */
507 if (gsn->cb_conf) gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
508 queue_freemsg(gsn->queue_req, qmsg);
510 else {
511 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
512 (struct sockaddr *) &qmsg->peer, sizeof(struct sockaddr_in)) < 0) {
513 gsn->err_sendto++;
514 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));
516 queue_back(gsn->queue_req, qmsg);
517 qmsg->timeout = now + 3;
518 qmsg->retrans++;
522 /* Also clean up reply timeouts */
523 while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
524 (qmsg->timeout < now)) {
525 /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL));*/
526 queue_freemsg(gsn->queue_resp, qmsg);
529 return 0;
532 int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout) {
533 time_t now, later;
534 struct qmsg_t *qmsg;
536 if (queue_getfirst(gsn->queue_req, &qmsg)) {
537 timeout->tv_sec = 10;
538 timeout->tv_usec = 0;
540 else {
541 now = time(NULL);
542 later = qmsg->timeout;
543 timeout->tv_sec = later - now;
544 timeout->tv_usec = 0;
545 if (timeout->tv_sec < 0) timeout->tv_sec = 0; /* No negative allowed */
546 if (timeout->tv_sec > 10) timeout->tv_sec = 10; /* Max sleep for 10 sec*/
548 return 0;
551 int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
552 union gtp_packet *packet, int len,
553 struct sockaddr_in *peer, int fd,
554 uint16_t seq, uint64_t tid) {
555 struct qmsg_t *qmsg;
557 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
558 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
559 packet->gtp0.h.seq = hton16(seq);
560 packet->gtp0.h.tid = tid;
561 if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
562 (packet->gtp0.h.type == GTP_ERROR)))
563 packet->gtp0.h.flow=hton16(pdp->flru);
564 else if (pdp)
565 packet->gtp0.h.flow=hton16(pdp->flrc);
567 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
568 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
569 packet->gtp1l.h.seq = hton16(seq);
570 if (pdp && (fd == gsn->fd1u))
571 packet->gtp1l.h.tei=hton32(pdp->teid_gn);
572 else if (pdp)
573 packet->gtp1l.h.tei=hton32(pdp->teic_gn);
575 else {
576 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
577 return -1;
580 if (fcntl(fd, F_SETFL, 0)) {
581 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
582 return -1;
585 if (sendto(fd, packet, len, 0,
586 (struct sockaddr *) peer, sizeof(struct sockaddr_in)) < 0) {
587 gsn->err_sendto++;
588 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
589 return -1;
592 /* Use new queue structure */
593 if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
594 gsn->err_queuefull++;
595 gtp_err(LOG_ERR, __FILE__, __LINE__, "Retransmit queue is full");
597 else {
598 memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
599 qmsg->l = len;
600 qmsg->timeout = time(NULL) + 60; /* When to timeout */
601 qmsg->retrans = 0; /* No retransmissions so far */
602 qmsg->cbp = NULL;
603 qmsg->type = 0;
604 qmsg->fd = fd;
606 return 0;
609 int gtp_notification(struct gsn_t *gsn, int version,
610 union gtp_packet *packet, int len,
611 struct sockaddr_in *peer, int fd,
612 uint16_t seq) {
614 struct sockaddr_in addr;
616 memcpy(&addr, peer, sizeof(addr));
618 /* In GTP0 notifications are treated as replies. In GTP1 they
619 are requests for which there is no reply */
621 if (fd == gsn->fd1c)
622 addr.sin_port = htons(GTP1C_PORT);
623 else if (fd == gsn->fd1u)
624 addr.sin_port = htons(GTP1C_PORT);
626 if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
627 packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
628 packet->gtp0.h.seq = hton16(seq);
630 else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
631 packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
632 packet->gtp1l.h.seq = hton16(seq);
634 else {
635 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
636 return -1;
639 if (fcntl(fd, F_SETFL, 0)) {
640 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
641 return -1;
644 if (sendto(fd, packet, len, 0,
645 (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) {
646 gsn->err_sendto++;
647 gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
648 return -1;
650 return 0;
653 int gtp_dublicate(struct gsn_t *gsn, int version,
654 struct sockaddr_in *peer, uint16_t seq) {
655 struct qmsg_t *qmsg;
657 if(queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
658 return EOF; /* Notfound */
661 if (fcntl(qmsg->fd, F_SETFL, 0)) {
662 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
663 return -1;
666 if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
667 (struct sockaddr *) peer, sizeof(struct sockaddr_in)) < 0) {
668 gsn->err_sendto++;
669 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));
671 return 0;
676 /* Perform restoration and recovery error handling as described in 29.060 */
677 static void log_restart(struct gsn_t *gsn) {
678 FILE *f;
679 int i;
680 int counter = 0;
681 char filename[NAMESIZE];
683 filename[NAMESIZE-1] = 0; /* No null term. guarantee by strncpy */
684 strncpy(filename, gsn->statedir, NAMESIZE-1);
685 strncat(filename, RESTART_FILE,
686 NAMESIZE-1-sizeof(RESTART_FILE));
688 i = umask(022);
690 /* We try to open file. On failure we will later try to create file */
691 if (!(f = fopen(filename, "r"))) {
693 gtp_err(LOG_ERR, __FILE__, __LINE__, "State information file (%s) not found. Creating new file.", filename);
695 else {
696 umask(i);
697 fscanf(f, "%d", &counter);
698 if (fclose(f)) {
699 gtp_err(LOG_ERR, __FILE__, __LINE__, "fclose failed: Error = %s", strerror(errno));
703 gsn->restart_counter = (unsigned char) counter;
704 gsn->restart_counter++;
706 if (!(f = fopen(filename, "w"))) {
707 gtp_err(LOG_ERR, __FILE__, __LINE__, "fopen(path=%s, mode=%s) failed: Error = %s", filename, "w", strerror(errno));
708 return;
711 umask(i);
712 fprintf(f, "%d\n", gsn->restart_counter);
713 if (fclose(f)) {
714 gtp_err(LOG_ERR, __FILE__, __LINE__, "fclose failed: Error = %s", strerror(errno));
715 return;
721 int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
722 int mode)
724 struct sockaddr_in addr;
726 syslog(LOG_ERR, "GTP: gtp_newgsn() started");
728 *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
730 (*gsn)->statedir = statedir;
731 log_restart(*gsn);
733 /* Initialise sequence number */
734 (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
736 /* Initialise request retransmit queue */
737 queue_new(&(*gsn)->queue_req);
738 queue_new(&(*gsn)->queue_resp);
740 /* Initialise pdp table */
741 pdp_init();
743 /* Initialise call back functions */
744 (*gsn)->cb_create_context_ind = 0;
745 (*gsn)->cb_delete_context = 0;
746 (*gsn)->cb_unsup_ind = 0;
747 (*gsn)->cb_conf = 0;
748 (*gsn)->cb_data_ind = 0;
750 /* Store function parameters */
751 (*gsn)->gsnc = *listen;
752 (*gsn)->gsnu = *listen;
753 (*gsn)->mode = mode;
756 /* Create GTP version 0 socket */
757 if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
758 (*gsn)->err_socket++;
759 gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
760 return -1;
763 memset(&addr, 0, sizeof(addr));
764 addr.sin_family = AF_INET;
765 addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
766 addr.sin_port = htons(GTP0_PORT);
767 #if defined(__FreeBSD__) || defined(__APPLE__)
768 addr.sin_len = sizeof(addr);
769 #endif
771 if (bind((*gsn)->fd0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
772 (*gsn)->err_socket++;
773 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));
774 return -1;
777 /* Create GTP version 1 control plane socket */
778 if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
779 (*gsn)->err_socket++;
780 gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
781 return -1;
784 memset(&addr, 0, sizeof(addr));
785 addr.sin_family = AF_INET;
786 addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
787 addr.sin_port = htons(GTP1C_PORT);
788 #if defined(__FreeBSD__) || defined(__APPLE__)
789 addr.sin_len = sizeof(addr);
790 #endif
792 if (bind((*gsn)->fd1c, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
793 (*gsn)->err_socket++;
794 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));
795 return -1;
798 /* Create GTP version 1 user plane socket */
799 if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
800 (*gsn)->err_socket++;
801 gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
802 return -1;
805 memset(&addr, 0, sizeof(addr));
806 addr.sin_family = AF_INET;
807 addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
808 addr.sin_port = htons(GTP1U_PORT);
809 #if defined(__FreeBSD__) || defined(__APPLE__)
810 addr.sin_len = sizeof(addr);
811 #endif
813 if (bind((*gsn)->fd1u, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
814 (*gsn)->err_socket++;
815 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));
816 return -1;
819 return 0;
822 int gtp_free(struct gsn_t *gsn) {
824 /* Clean up retransmit queues */
825 queue_free(gsn->queue_req);
826 queue_free(gsn->queue_resp);
828 close(gsn->fd0);
829 close(gsn->fd1c);
830 close(gsn->fd1u);
832 free(gsn);
833 return 0;
836 /* ***********************************************************
837 * Path management messages
838 * Messages: echo and version not supported.
839 * A path is connection between two UDP/IP endpoints
841 * A path is either using GTP0 or GTP1. A path can be
842 * established by any kind of GTP message??
844 * Which source port to use?
845 * GTP-C request destination port is 2123/3386
846 * GTP-U request destination port is 2152/3386
847 * T-PDU destination port is 2152/3386.
848 * For the above messages the source port is locally allocated.
849 * For response messages src=rx-dst and dst=rx-src.
850 * For simplicity we should probably use 2123+2152/3386 as
851 * src port even for the cases where src can be locally
852 * allocated. This also means that we have to listen only to
853 * the same ports.
854 * For response messages we need to be able to respond to
855 * the relevant src port even if it is locally allocated by
856 * the peer.
858 * The need for path management!
859 * We might need to keep a list of active paths. This might
860 * be in the form of remote IP address + UDP port numbers.
861 * (We will consider a path astablished if we have a context
862 * with the node in question)
863 *************************************************************/
865 /* Send off an echo request */
866 int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
867 struct in_addr *inetaddr)
869 union gtp_packet packet;
870 unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
871 return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
874 /* Send off an echo reply */
875 int gtp_echo_resp(struct gsn_t *gsn, int version,
876 struct sockaddr_in *peer, int fd,
877 void *pack, unsigned len)
879 union gtp_packet packet;
880 unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
881 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY, gsn->restart_counter);
882 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
883 get_seq(pack), get_tid(pack));
887 /* Handle a received echo request */
888 int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
889 int fd, void *pack, unsigned len) {
891 /* Check if it was a dublicate request */
892 if(!gtp_dublicate(gsn, 0, peer, get_seq(pack))) return 0;
894 /* Send off reply to request */
895 return gtp_echo_resp(gsn, version, peer, fd, pack, len);
898 /* Handle a received echo reply */
899 int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
900 void *pack, unsigned len) {
901 union gtpie_member *ie[GTPIE_SIZE];
902 unsigned char recovery;
903 void *cbp = NULL;
904 uint8_t type = 0;
905 int hlen = get_hlen(pack);
907 /* Remove packet from queue */
908 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
910 /* Extract information elements into a pointer array */
911 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
912 gsn->invalid++;
913 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
914 "Invalid message format");
915 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
916 return EOF;
919 if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
920 gsn->missing++;
921 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
922 "Missing mandatory field");
923 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
924 return EOF;
927 /* Echo reply packages does not have a cause information element */
928 /* Instead we return the recovery number in the callback function */
929 if (gsn->cb_conf) gsn->cb_conf(type, recovery, NULL, cbp);
931 return 0;
934 /* Send off a Version Not Supported message */
935 /* This message is somewhat special in that it actually is a
936 * response to some other message with unsupported GTP version
937 * For this reason it has parameters like a response, and does
938 * its own message transmission. No signalling queue is used
939 * The reply is sent to the peer IP and peer UDP. This means that
940 * the peer will be receiving a GTP0 message on a GTP1 port!
941 * In practice however this will never happen as a GTP0 GSN will
942 * only listen to the GTP0 port, and therefore will never receive
943 * anything else than GTP0 */
945 int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
946 int fd, void *pack, unsigned len)
948 union gtp_packet packet;
950 /* GTP 1 is the highest supported protocol */
951 unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
952 return gtp_notification(gsn, version, &packet, length,
953 peer, fd, 0);
956 /* Handle a Version Not Supported message */
957 int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
958 void *pack, unsigned len) {
960 if (gsn->cb_unsup_ind) gsn->cb_unsup_ind(peer);
962 return 0;
965 /* Send off an Supported Extension Headers Notification */
966 int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
967 int fd, void *pack, unsigned len)
969 union gtp_packet packet;
970 unsigned int length = get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
972 uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
974 if (version < 1)
975 return 0;
977 /* We report back that we support only PDCP PDU headers */
978 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T, sizeof(pdcp_pdu),
979 &pdcp_pdu);
981 return gtp_notification(gsn, version, &packet, length,
982 peer, fd, get_seq(pack));
985 /* Handle a Supported Extension Headers Notification */
986 int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
987 void *pack, unsigned len) {
989 if (gsn->cb_extheader_ind) gsn->cb_extheader_ind(peer);
991 return 0;
995 /* ***********************************************************
996 * Session management messages
997 * Messages: create, update and delete PDP context
999 * Information storage
1000 * Information storage for each PDP context is defined in
1001 * 23.060 section 13.3. Includes IMSI, MSISDN, APN, PDP-type,
1002 * PDP-address (IP address), sequence numbers, charging ID.
1003 * For the SGSN it also includes radio related mobility
1004 * information.
1005 *************************************************************/
1007 /* API: Send Create PDP Context Request */
1008 extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
1009 void *cbp) {
1010 union gtp_packet packet;
1011 unsigned int length = get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
1012 struct pdp_t *linked_pdp = NULL;
1014 /* TODO: Secondary PDP Context Activation Procedure */
1015 /* In secondary activation procedure the PDP context is identified
1016 by tei in the header. The following fields are omitted: Selection
1017 mode, IMSI, MSISDN, End User Address, Access Point Name and
1018 Protocol Configuration Options */
1020 if (pdp->secondary) {
1021 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
1022 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown linked PDP context");
1023 return EOF;
1027 if (pdp->version == 0) {
1028 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1029 sizeof(pdp->qos_req0), pdp->qos_req0);
1032 if (pdp->version == 1) {
1033 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1034 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1035 sizeof(pdp->imsi), (uint8_t*) &pdp->imsi);
1038 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1039 gsn->restart_counter);
1041 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1042 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
1043 pdp->selmode);
1045 if (pdp->version == 0) {
1046 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1047 pdp->fllu);
1048 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1049 pdp->fllc);
1052 if (pdp->version == 1) {
1053 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1054 pdp->teid_own);
1056 if (!pdp->teic_confirmed)
1057 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1058 pdp->teic_own);
1060 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1061 pdp->nsapi);
1063 if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
1064 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1065 linked_pdp->nsapi);
1067 if (pdp->cch_pdp) /* Only include charging if flags are set */
1068 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
1069 pdp->cch_pdp);
1072 /* TODO
1073 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1074 pdp->traceref);
1075 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1076 pdp->tracetype); */
1078 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1079 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1080 pdp->eua.l, pdp->eua.v);
1083 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1084 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
1085 pdp->apn_use.l, pdp->apn_use.v);
1087 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1088 if (pdp->pco_req.l)
1089 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1090 pdp->pco_req.l, pdp->pco_req.v);
1092 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1093 pdp->gsnlc.l, pdp->gsnlc.v);
1094 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1095 pdp->gsnlu.l, pdp->gsnlu.v);
1097 if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
1098 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
1099 pdp->msisdn.l, pdp->msisdn.v);
1101 if (pdp->version == 1)
1102 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1103 pdp->qos_req.l, pdp->qos_req.v);
1106 if ((pdp->version == 1) && pdp->tft.l)
1107 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1108 pdp->tft.l, pdp->tft.v);
1110 if ((pdp->version == 1) && pdp->triggerid.l)
1111 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1112 pdp->triggerid.l, pdp->triggerid.v);
1114 if ((pdp->version == 1) && pdp->omcid.l)
1115 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1116 pdp->omcid.l, pdp->omcid.v);
1118 /* TODO hisaddr0 */
1119 gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp);
1121 return 0;
1124 /* API: Application response to context indication */
1125 int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause) {
1127 /* Now send off a reply to the peer */
1128 gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
1130 if (cause != GTPCAUSE_ACC_REQ) {
1131 pdp_freepdp(pdp);
1134 return 0;
1137 /* API: Register create context indication callback */
1138 int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
1139 int (*cb_create_context_ind) (struct pdp_t* pdp))
1141 gsn->cb_create_context_ind = cb_create_context_ind;
1142 return 0;
1146 /* Send Create PDP Context Response */
1147 int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
1148 uint8_t cause) {
1149 union gtp_packet packet;
1150 unsigned int length = get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
1152 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
1154 if (cause == GTPCAUSE_ACC_REQ) {
1156 if (version == 0)
1157 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1158 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1160 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
1161 pdp->reorder);
1162 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1163 gsn->restart_counter);
1165 if (version == 0) {
1166 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1167 pdp->fllu);
1168 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1169 pdp->fllc);
1172 if (version == 1) {
1173 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1174 pdp->teid_own);
1175 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1176 pdp->teic_own);
1179 /* TODO: We use teic_own as charging ID */
1180 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1181 pdp->teic_own);
1183 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1184 pdp->eua.l, pdp->eua.v);
1186 if (pdp->pco_neg.l) { /* Optional PCO */
1187 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
1188 pdp->pco_neg.l, pdp->pco_neg.v);
1191 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1192 pdp->gsnlc.l, pdp->gsnlc.v);
1193 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1194 pdp->gsnlu.l, pdp->gsnlu.v);
1196 if (version == 1)
1197 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1198 pdp->qos_neg.l, pdp->qos_neg.v);
1200 /* TODO: Charging gateway address */
1203 return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
1204 pdp->fd, pdp->seq, pdp->tid);
1207 /* Handle Create PDP Context Request */
1208 int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
1209 struct sockaddr_in *peer, int fd,
1210 void *pack, unsigned len) {
1211 struct pdp_t *pdp, *pdp_old;
1212 struct pdp_t pdp_buf;
1213 union gtpie_member* ie[GTPIE_SIZE];
1214 uint8_t recovery;
1216 uint16_t seq = get_seq(pack);
1217 int hlen = get_hlen(pack);
1218 uint8_t linked_nsapi = 0;
1219 struct pdp_t *linked_pdp = NULL;
1221 if(!gtp_dublicate(gsn, version, peer, seq)) return 0;
1223 pdp = &pdp_buf;
1224 memset(pdp, 0, sizeof(struct pdp_t));
1226 if (version == 0) {
1227 pdp->imsi = ((union gtp_packet*)pack)->gtp0.h.tid & 0x0fffffffffffffffull;
1228 pdp->nsapi = (((union gtp_packet*)pack)->gtp0.h.tid & 0xf000000000000000ull) >> 60;
1231 pdp->seq = seq;
1232 pdp->sa_peer = *peer;
1233 pdp->fd = fd;
1234 pdp->version = version;
1236 /* Decode information elements */
1237 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
1238 gsn->invalid++;
1239 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1240 "Invalid message format");
1241 if (0 == version)
1242 return EOF;
1243 else
1244 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_INVALID_MESSAGE);
1247 if (version == 1) {
1248 /* Linked NSAPI (conditional) */
1249 /* If included this is the Secondary PDP Context Activation Procedure */
1250 /* In secondary activation IMSI is not included, so the context must be */
1251 /* identified by the tei */
1252 if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
1254 /* Find the primary PDP context */
1255 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
1256 gsn->incorrect++;
1257 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1258 "Incorrect optional information field");
1259 return gtp_create_pdp_resp(gsn, version, pdp,
1260 GTPCAUSE_OPT_IE_INCORRECT);
1263 /* Check that the primary PDP context matches linked nsapi */
1264 if (linked_pdp->nsapi != linked_nsapi) {
1265 gsn->incorrect++;
1266 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1267 "Incorrect optional information field");
1268 return gtp_create_pdp_resp(gsn, version, pdp,
1269 GTPCAUSE_OPT_IE_INCORRECT);
1272 /* Copy parameters from primary context */
1273 pdp->selmode = linked_pdp->selmode;
1274 pdp->imsi = linked_pdp->imsi;
1275 pdp->msisdn = linked_pdp->msisdn;
1276 pdp->eua = linked_pdp->eua;
1277 pdp->pco_req = linked_pdp->pco_req;
1278 pdp->apn_req = linked_pdp->apn_req;
1279 pdp->teic_gn = linked_pdp->teic_gn;
1280 pdp->secondary = 1;
1282 } /* if (version == 1) */
1284 if (version == 0) {
1285 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1286 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1287 gsn->missing++;
1288 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1289 "Missing mandatory information field");
1290 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_MAN_IE_MISSING);
1294 if ((version == 1) && (!linked_pdp)) {
1295 /* Not Secondary PDP Context Activation Procedure */
1296 /* IMSI (conditional) */
1297 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
1298 gsn->missing++;
1299 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1300 "Missing mandatory information field");
1301 return gtp_create_pdp_resp(gsn, version, pdp,
1302 GTPCAUSE_MAN_IE_MISSING);
1306 /* Recovery (optional) */
1307 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1308 /* TODO: Handle received recovery IE */
1311 /* Selection mode (conditional) */
1312 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1313 if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
1314 &pdp->selmode, sizeof(pdp->selmode))) {
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);
1323 if (version == 0) {
1324 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1325 gsn->missing++;
1326 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1327 "Missing mandatory information field");
1328 return gtp_create_pdp_resp(gsn, version, pdp,
1329 GTPCAUSE_MAN_IE_MISSING);
1332 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1333 gsn->missing++;
1334 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1335 "Missing mandatory information field");
1336 return gtp_create_pdp_resp(gsn, version, pdp,
1337 GTPCAUSE_MAN_IE_MISSING);
1342 if (version == 1) {
1343 /* TEID (mandatory) */
1344 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_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);
1352 /* TEIC (conditional) */
1353 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1354 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1355 gsn->missing++;
1356 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1357 "Missing mandatory information field");
1358 return gtp_create_pdp_resp(gsn, version, pdp,
1359 GTPCAUSE_MAN_IE_MISSING);
1363 /* NSAPI (mandatory) */
1364 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
1365 gsn->missing++;
1366 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1367 "Missing mandatory information field");
1368 return gtp_create_pdp_resp(gsn, version, pdp,
1369 GTPCAUSE_MAN_IE_MISSING);
1374 /* Charging Characteriatics (optional) */
1375 /* Trace reference (optional) */
1376 /* Trace type (optional) */
1377 /* Charging Characteriatics (optional) */
1379 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1380 /* End User Address (conditional) */
1381 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1382 &pdp->eua.v, sizeof(pdp->eua.v))) {
1383 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);
1390 /* APN */
1391 if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
1392 &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
1393 gsn->missing++;
1394 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1395 "Missing mandatory information field");
1396 return gtp_create_pdp_resp(gsn, version, pdp,
1397 GTPCAUSE_MAN_IE_MISSING);
1400 /* Extract protocol configuration options (optional) */
1401 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1402 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1406 /* SGSN address for signalling (mandatory) */
1407 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1408 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1409 gsn->missing++;
1410 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1411 "Missing mandatory information field");
1412 return gtp_create_pdp_resp(gsn, version, pdp,
1413 GTPCAUSE_MAN_IE_MISSING);
1416 /* SGSN address for user traffic (mandatory) */
1417 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1418 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1419 gsn->missing++;
1420 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1421 "Missing mandatory information field");
1422 return gtp_create_pdp_resp(gsn, version, pdp,
1423 GTPCAUSE_MAN_IE_MISSING);
1426 if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
1427 /* MSISDN (conditional) */
1428 if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
1429 &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
1430 gsn->missing++;
1431 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1432 "Missing mandatory information field");
1433 return gtp_create_pdp_resp(gsn, version, pdp,
1434 GTPCAUSE_MAN_IE_MISSING);
1438 if (version == 1) {
1439 /* QoS (mandatory) */
1440 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
1441 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
1442 gsn->missing++;
1443 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1444 "Missing mandatory information field");
1445 return gtp_create_pdp_resp(gsn, version, pdp,
1446 GTPCAUSE_MAN_IE_MISSING);
1449 /* TFT (conditional) */
1450 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
1451 &pdp->tft.v, sizeof(pdp->tft.v))) {
1454 /* Trigger ID */
1455 /* OMC identity */
1458 /* Initialize our own IP addresses */
1459 in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
1460 in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
1462 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Before pdp_tidget\n");
1464 if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
1465 /* Found old pdp with same tid. Now the voodoo begins! */
1466 /* 09.60 / 29.060 allows create on existing context to "steal" */
1467 /* the context which was allready established */
1468 /* We check that the APN, selection mode and MSISDN is the same */
1469 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Old context found\n");
1470 if ((pdp->apn_req.l == pdp_old->apn_req.l)
1471 && (!memcmp(pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
1472 && (pdp->selmode == pdp_old->selmode)
1473 && (pdp->msisdn.l == pdp_old->msisdn.l)
1474 && (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l))) {
1475 /* OK! We are dealing with the same APN. We will copy new
1476 * parameters to the old pdp and send off confirmation
1477 * We ignore the following information elements:
1478 * QoS: MS will get originally negotiated QoS.
1479 * End user address (EUA). MS will get old EUA anyway.
1480 * Protocol configuration option (PCO): Only application can verify */
1482 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Old context found\n");
1484 /* Copy remote flow label */
1485 pdp_old->flru = pdp->flru;
1486 pdp_old->flrc = pdp->flrc;
1488 /* Copy remote tei */
1489 pdp_old->teid_gn = pdp->teid_gn;
1490 pdp_old->teic_gn = pdp->teic_gn;
1492 /* Copy peer GSN address */
1493 pdp_old->gsnrc.l = pdp->gsnrc.l;
1494 memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
1495 pdp_old->gsnru.l = pdp->gsnru.l;
1496 memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
1498 /* Copy request parameters */
1499 pdp_old->seq = pdp->seq;
1500 pdp_old->sa_peer = pdp->sa_peer;
1501 pdp_old->fd = pdp->fd = fd;
1502 pdp_old->version = pdp->version = version;
1504 /* Switch to using the old pdp context */
1505 pdp = pdp_old;
1507 /* Confirm to peer that things were "successful" */
1508 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_ACC_REQ);
1510 else { /* This is not the same PDP context. Delete the old one. */
1512 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Deleting old context\n");
1514 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp_old);
1515 pdp_freepdp(pdp_old);
1517 if (GTP_DEBUG) printf("gtp_create_pdp_ind: Deleted...\n");
1521 pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
1523 /* Callback function to validata login */
1524 if (gsn->cb_create_context_ind !=0)
1525 return gsn->cb_create_context_ind(pdp);
1526 else {
1527 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1528 "No create_context_ind callback defined");
1529 return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_NOT_SUPPORTED);
1534 /* Handle Create PDP Context Response */
1535 int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
1536 struct sockaddr_in *peer,
1537 void *pack, unsigned len) {
1538 struct pdp_t *pdp;
1539 union gtpie_member *ie[GTPIE_SIZE];
1540 uint8_t cause, recovery;
1541 void *cbp = NULL;
1542 uint8_t type = 0;
1543 int hlen = get_hlen(pack);
1545 /* Remove packet from queue */
1546 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
1548 /* Find the context in question */
1549 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1550 gsn->err_unknownpdp++;
1551 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1552 "Unknown PDP context");
1553 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
1554 return EOF;
1557 /* Register that we have received a valid teic from GGSN */
1558 pdp->teic_confirmed = 1;
1560 /* Decode information elements */
1561 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
1562 gsn->invalid++;
1563 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1564 "Invalid message format");
1565 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1566 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1567 pdp_freepdp(pdp); */
1568 return EOF;
1571 /* Extract cause value (mandatory) */
1572 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
1573 gsn->missing++;
1574 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1575 "Missing mandatory information field");
1576 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1577 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1578 pdp_freepdp(pdp); */
1579 return EOF;
1582 /* Extract recovery (optional) */
1583 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1584 /* TODO: Handle received recovery IE */
1587 /* Extract protocol configuration options (optional) */
1588 if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
1589 &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
1592 /* Check all conditional information elements */
1593 if (GTPCAUSE_ACC_REQ == cause) {
1595 if (version == 0) {
1596 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1597 &pdp->qos_neg0, sizeof(pdp->qos_neg0))) {
1598 gsn->missing++;
1599 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1600 "Missing conditional information field");
1601 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1602 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1603 pdp_freepdp(pdp); */
1604 return EOF;
1608 if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
1609 gsn->missing++;
1610 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1611 "Missing conditional information field");
1612 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1613 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1614 pdp_freepdp(pdp); */
1615 return EOF;
1618 if (version == 0) {
1619 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
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 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1625 pdp_freepdp(pdp); */
1626 return EOF;
1629 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1630 gsn->missing++;
1631 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1632 "Missing conditional information field");
1633 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1634 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1635 pdp_freepdp(pdp); */
1636 return EOF;
1640 if (version == 1) {
1641 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1642 gsn->missing++;
1643 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1644 "Missing conditional information field");
1645 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1646 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1647 pdp_freepdp(pdp); */
1648 return EOF;
1651 if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
1652 gsn->missing++;
1653 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1654 "Missing conditional information field");
1655 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1656 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1657 pdp_freepdp(pdp); */
1658 return EOF;
1662 if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
1663 gsn->missing++;
1664 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1665 "Missing conditional information field");
1666 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1667 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1668 pdp_freepdp(pdp); */
1671 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
1672 &pdp->eua.v, sizeof(pdp->eua.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 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1678 pdp_freepdp(pdp); */
1679 return EOF;
1682 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
1683 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
1684 gsn->missing++;
1685 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1686 "Missing conditional information field");
1687 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1688 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1689 pdp_freepdp(pdp); */
1690 return EOF;
1693 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
1694 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
1695 gsn->missing++;
1696 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1697 "Missing conditional information field");
1698 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1699 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1700 pdp_freepdp(pdp); */
1701 return EOF;
1704 if (version == 1) {
1705 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
1706 &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
1707 gsn->missing++;
1708 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1709 "Missing conditional information field");
1710 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
1711 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
1712 pdp_freepdp(pdp); */
1713 return EOF;
1719 if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
1721 return 0;
1725 /* API: Send Update PDP Context Request */
1726 int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
1727 struct in_addr* inetaddr) {
1728 union gtp_packet packet;
1729 unsigned int length = get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
1731 if (pdp->version == 0)
1732 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1733 sizeof(pdp->qos_req0), pdp->qos_req0);
1735 /* Include IMSI if updating with unknown teic_gn */
1736 if ((pdp->version == 1) && (!pdp->teic_gn))
1737 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
1738 sizeof(pdp->imsi), (uint8_t*) &pdp->imsi);
1740 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1741 gsn->restart_counter);
1743 if (pdp->version == 0) {
1744 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1745 pdp->fllu);
1746 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1747 pdp->fllc);
1750 if (pdp->version == 1) {
1751 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1752 pdp->teid_own);
1754 if (!pdp->teic_confirmed)
1755 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1756 pdp->teic_own);
1759 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
1760 pdp->nsapi);
1762 /* TODO
1763 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1764 pdp->traceref);
1765 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
1766 pdp->tracetype); */
1768 /* TODO if ggsn update message
1769 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1770 pdp->eua.l, pdp->eua.v);
1773 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1774 pdp->gsnlc.l, pdp->gsnlc.v);
1775 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1776 pdp->gsnlu.l, pdp->gsnlu.v);
1778 if (pdp->version == 1)
1779 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1780 pdp->qos_req.l, pdp->qos_req.v);
1783 if ((pdp->version == 1) && pdp->tft.l)
1784 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
1785 pdp->tft.l, pdp->tft.v);
1787 if ((pdp->version == 1) && pdp->triggerid.l)
1788 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
1789 pdp->triggerid.l, pdp->triggerid.v);
1791 if ((pdp->version == 1) && pdp->omcid.l)
1792 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
1793 pdp->omcid.l, pdp->omcid.v);
1795 gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
1797 return 0;
1801 /* Send Update PDP Context Response */
1802 int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
1803 struct sockaddr_in *peer, int fd,
1804 void *pack, unsigned len,
1805 struct pdp_t *pdp, uint8_t cause) {
1807 union gtp_packet packet;
1808 unsigned int length = get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
1810 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
1812 if (cause == GTPCAUSE_ACC_REQ) {
1814 if (version == 0)
1815 gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
1816 sizeof(pdp->qos_neg0), pdp->qos_neg0);
1818 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
1819 gsn->restart_counter);
1821 if (version == 0) {
1822 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
1823 pdp->fllu);
1824 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
1825 pdp->fllc);
1828 if (version == 1) {
1829 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
1830 pdp->teid_own);
1832 if (!pdp->teic_confirmed)
1833 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
1834 pdp->teic_own);
1837 /* TODO we use teid_own as charging ID address */
1838 gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
1839 pdp->teid_own);
1841 /* If ggsn
1842 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
1843 pdp->eua.l, pdp->eua.v); */
1845 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1846 pdp->gsnlc.l, pdp->gsnlc.v);
1847 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
1848 pdp->gsnlu.l, pdp->gsnlu.v);
1850 if (version == 1)
1851 gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
1852 pdp->qos_neg.l, pdp->qos_neg.v);
1854 /* TODO: Charging gateway address */
1857 return gtp_resp(version, gsn, pdp, &packet, length, peer,
1858 fd, get_seq(pack), get_tid(pack));
1862 /* Handle Update PDP Context Request */
1863 int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
1864 struct sockaddr_in *peer, int fd,
1865 void *pack, unsigned len) {
1866 struct pdp_t *pdp;
1867 struct pdp_t pdp_backup;
1868 union gtpie_member* ie[GTPIE_SIZE];
1869 uint8_t recovery;
1871 uint16_t seq = get_seq(pack);
1872 int hlen = get_hlen(pack);
1874 uint64_t imsi;
1875 uint8_t nsapi;
1877 /* Is this a dublicate ? */
1878 if(!gtp_dublicate(gsn, version, peer, seq)) {
1879 return 0; /* We allready send of response once */
1883 /* Decode information elements */
1884 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
1885 gsn->invalid++;
1886 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1887 "Invalid message format");
1888 if (0 == version)
1889 return EOF;
1890 else
1891 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1892 NULL, GTPCAUSE_INVALID_MESSAGE);
1895 /* Finding PDP: */
1896 /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
1897 /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
1898 /* we have to use the tunnel endpoint identifier */
1899 if (version == 0) {
1900 imsi = ((union gtp_packet*)pack)->gtp0.h.tid & 0x0fffffffffffffffull;
1901 nsapi = (((union gtp_packet*)pack)->gtp0.h.tid & 0xf000000000000000ull) >> 60;
1903 /* Find the context in question */
1904 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1905 gsn->err_unknownpdp++;
1906 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1907 "Unknown PDP context");
1908 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1909 NULL, GTPCAUSE_NON_EXIST);
1912 else if (version == 1) {
1913 /* NSAPI (mandatory) */
1914 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
1915 gsn->missing++;
1916 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1917 "Missing mandatory information field");
1918 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1919 NULL, GTPCAUSE_MAN_IE_MISSING);
1922 /* IMSI (conditional) */
1923 if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
1924 /* Find the context in question */
1925 if (pdp_getgtp1(&pdp, get_tei(pack))) {
1926 gsn->err_unknownpdp++;
1927 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1928 "Unknown PDP context");
1929 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1930 NULL, GTPCAUSE_NON_EXIST);
1933 else {
1934 /* Find the context in question */
1935 if (pdp_getimsi(&pdp, imsi, nsapi)) {
1936 gsn->err_unknownpdp++;
1937 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1938 "Unknown PDP context");
1939 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1940 NULL, GTPCAUSE_NON_EXIST);
1944 else {
1945 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
1946 return EOF;
1949 /* Make a backup copy in case anything is wrong */
1950 memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
1952 if (version == 0) {
1953 if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
1954 pdp->qos_req0, sizeof(pdp->qos_req0))) {
1955 gsn->missing++;
1956 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1957 "Missing mandatory information field");
1958 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1959 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
1960 pdp, GTPCAUSE_MAN_IE_MISSING);
1964 /* Recovery (optional) */
1965 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
1966 /* TODO: Handle received recovery IE */
1969 if (version == 0) {
1970 if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
1971 gsn->missing++;
1972 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1973 "Missing mandatory information field");
1974 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1975 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1976 GTPCAUSE_MAN_IE_MISSING);
1979 if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
1980 gsn->missing++;
1981 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1982 "Missing mandatory information field");
1983 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1984 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1985 GTPCAUSE_MAN_IE_MISSING);
1990 if (version == 1) {
1991 /* TEID (mandatory) */
1992 if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
1993 gsn->missing++;
1994 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
1995 "Missing mandatory information field");
1996 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
1997 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
1998 GTPCAUSE_MAN_IE_MISSING);
2001 /* TEIC (conditional) */
2002 /* If TEIC is not included it means that we have allready received it */
2003 /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
2004 /* all updated contexts, or only for one of the linked contexts */
2005 gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
2007 /* NSAPI (mandatory) */
2008 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
2009 gsn->missing++;
2010 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2011 "Missing mandatory information field");
2012 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2013 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2014 GTPCAUSE_MAN_IE_MISSING);
2018 /* Trace reference (optional) */
2019 /* Trace type (optional) */
2021 /* End User Address (conditional) TODO: GGSN Initiated
2022 if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2023 &pdp->eua.v, sizeof(pdp->eua.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, pdp,
2029 GTPCAUSE_MAN_IE_MISSING);
2030 } */
2033 /* SGSN address for signalling (mandatory) */
2034 /* It is weird that this is mandatory when TEIC is conditional */
2035 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2036 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
2037 gsn->missing++;
2038 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2039 "Missing mandatory information field");
2040 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2041 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2042 GTPCAUSE_MAN_IE_MISSING);
2045 /* SGSN address for user traffic (mandatory) */
2046 if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2047 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
2048 gsn->missing++;
2049 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2050 "Missing mandatory information field");
2051 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2052 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2053 GTPCAUSE_MAN_IE_MISSING);
2056 if (version == 1) {
2057 /* QoS (mandatory) */
2058 if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
2059 &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
2060 gsn->missing++;
2061 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2062 "Missing mandatory information field");
2063 memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
2064 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2065 GTPCAUSE_MAN_IE_MISSING);
2068 /* TFT (conditional) */
2069 if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
2070 &pdp->tft.v, sizeof(pdp->tft.v))) {
2073 /* OMC identity */
2076 /* Confirm to peer that things were "successful" */
2077 return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
2078 GTPCAUSE_ACC_REQ);
2082 /* Handle Update PDP Context Response */
2083 int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
2084 struct sockaddr_in *peer,
2085 void *pack, unsigned len) {
2086 struct pdp_t *pdp;
2087 union gtpie_member *ie[GTPIE_SIZE];
2088 uint8_t cause, recovery;
2089 void *cbp = NULL;
2090 uint8_t type = 0;
2092 /* Remove packet from queue */
2093 if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp)) return EOF;
2095 /* Find the context in question */
2096 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet*)pack)->gtp0.h.flow))) {
2097 gsn->err_unknownpdp++;
2098 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2099 "Unknown PDP context");
2100 if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
2101 return EOF;
2104 /* Register that we have received a valid teic from GGSN */
2105 pdp->teic_confirmed = 1;
2107 /* Decode information elements */
2108 if (gtpie_decaps(ie, 0, pack+GTP0_HEADER_SIZE, len-GTP0_HEADER_SIZE)) {
2109 gsn->invalid++;
2110 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2111 "Invalid message format");
2112 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
2113 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2114 pdp_freepdp(pdp); */
2115 return EOF;
2118 /* Extract cause value (mandatory) */
2119 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2120 gsn->missing++;
2121 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2122 "Missing mandatory information field");
2123 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
2124 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2125 pdp_freepdp(pdp); */
2126 return EOF;
2129 /* Extract recovery (optional) */
2130 if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
2131 /* TODO: Handle received recovery IE */
2134 /* Check all conditional information elements */
2135 if (GTPCAUSE_ACC_REQ != cause) {
2136 if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
2137 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2138 pdp_freepdp(pdp); */
2139 return 0;
2141 else {
2142 /* Check for missing conditionary information elements */
2143 if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
2144 gtpie_exist(ie, GTPIE_REORDER, 0) &&
2145 gtpie_exist(ie, GTPIE_FL_DI, 0) &&
2146 gtpie_exist(ie, GTPIE_FL_C, 0) &&
2147 gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
2148 gtpie_exist(ie, GTPIE_EUA, 0) &&
2149 gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
2150 gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
2151 gsn->missing++;
2152 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2153 "Missing conditional information field");
2154 if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
2155 /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2156 pdp_freepdp(pdp); */
2157 return EOF;
2160 /* Update pdp with new values */
2161 gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
2162 pdp->qos_neg0, sizeof(pdp->qos_neg0));
2163 gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
2164 gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
2165 gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
2166 gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
2167 gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
2168 &pdp->eua.v, sizeof(pdp->eua.v));
2169 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
2170 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
2171 gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
2172 &pdp->gsnru.v, sizeof(pdp->gsnru.v));
2174 if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
2175 return 0; /* Succes */
2180 /* API: Send Delete PDP Context Request */
2181 int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
2182 int teardown) {
2183 union gtp_packet packet;
2184 unsigned int length = get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
2185 struct in_addr addr;
2186 struct pdp_t *linked_pdp;
2187 struct pdp_t *secondary_pdp;
2188 int n;
2189 int count = 0;
2191 if (gsna2in_addr(&addr, &pdp->gsnrc)) {
2192 gsn->err_address++;
2193 gtp_err(LOG_ERR, __FILE__, __LINE__, "GSN address conversion failed");
2194 return EOF;
2197 if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
2198 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown linked PDP context");
2199 return EOF;
2202 if (!teardown) {
2203 for (n=0; n< PDP_MAXNSAPI; n++)
2204 if (linked_pdp->secondary_tei[n]) count++;
2205 if (count <= 1) {
2206 gtp_err(LOG_ERR, __FILE__, __LINE__,
2207 "Must use teardown for last context");
2208 return EOF;
2212 if (pdp->version == 1) {
2213 if (teardown)
2214 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
2215 0xff);
2217 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
2218 pdp->nsapi);
2221 gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
2223 if (teardown) { /* Remove all contexts */
2224 for (n=0; n< PDP_MAXNSAPI; n++) {
2225 if (linked_pdp->secondary_tei[n]) {
2226 if (pdp_getgtp1(&secondary_pdp, linked_pdp->secondary_tei[n])) {
2227 gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown secondary PDP context");
2228 return EOF;
2230 if (linked_pdp != secondary_pdp) {
2231 if (gsn->cb_delete_context) gsn->cb_delete_context(secondary_pdp);
2232 pdp_freepdp(secondary_pdp);
2236 if (gsn->cb_delete_context) gsn->cb_delete_context(linked_pdp);
2237 pdp_freepdp(linked_pdp);
2239 else {
2240 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2241 if (pdp == linked_pdp) {
2242 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2243 linked_pdp->nodata = 1;
2245 else
2246 pdp_freepdp(pdp);
2249 return 0;
2252 /* Send Delete PDP Context Response */
2253 int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
2254 struct sockaddr_in *peer, int fd,
2255 void *pack, unsigned len,
2256 struct pdp_t *pdp, struct pdp_t *linked_pdp,
2257 uint8_t cause, int teardown)
2259 union gtp_packet packet;
2260 struct pdp_t *secondary_pdp;
2261 unsigned int length = get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
2262 int n;
2264 gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
2266 gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
2267 get_seq(pack), get_tid(pack));
2269 if (cause == GTPCAUSE_ACC_REQ) {
2270 if ((teardown) || (version == 0)) { /* Remove all contexts */
2271 for (n=0; n< PDP_MAXNSAPI; n++) {
2272 if (linked_pdp->secondary_tei[n]) {
2273 if (pdp_getgtp1(&secondary_pdp, linked_pdp->secondary_tei[n])) {
2274 gtp_err(LOG_ERR, __FILE__, __LINE__,
2275 "Unknown secondary PDP context");
2276 return EOF;
2278 if (linked_pdp != secondary_pdp) {
2279 if (gsn->cb_delete_context) gsn->cb_delete_context(secondary_pdp);
2280 pdp_freepdp(secondary_pdp);
2284 if (gsn->cb_delete_context) gsn->cb_delete_context(linked_pdp);
2285 pdp_freepdp(linked_pdp);
2287 else { /* Remove only current context */
2288 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2289 if (pdp == linked_pdp) {
2290 linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
2291 linked_pdp->nodata = 1;
2293 else
2294 pdp_freepdp(pdp);
2296 } /* if (cause == GTPCAUSE_ACC_REQ) */
2298 return 0;
2301 /* Handle Delete PDP Context Request */
2302 int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
2303 struct sockaddr_in *peer, int fd,
2304 void *pack, unsigned len) {
2305 struct pdp_t *pdp = NULL;
2306 struct pdp_t *linked_pdp = NULL;
2307 union gtpie_member* ie[GTPIE_SIZE];
2309 uint16_t seq = get_seq(pack);
2310 int hlen = get_hlen(pack);
2312 uint8_t nsapi;
2313 uint8_t teardown = 0;
2314 int n;
2315 int count = 0;
2317 /* Is this a dublicate ? */
2318 if(!gtp_dublicate(gsn, version, peer, seq)) {
2319 return 0; /* We allready send off response once */
2322 /* Find the linked context in question */
2323 if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
2324 gsn->err_unknownpdp++;
2325 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2326 "Unknown PDP context");
2327 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2328 GTPCAUSE_NON_EXIST, teardown);
2331 /* If version 0 this is also the secondary context */
2332 if (version == 0)
2333 pdp = linked_pdp;
2335 /* Decode information elements */
2336 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
2337 gsn->invalid++;
2338 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2339 "Invalid message format");
2340 if (0 == version)
2341 return EOF;
2342 else
2343 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2344 GTPCAUSE_INVALID_MESSAGE, teardown);
2347 if (version == 1) {
2348 /* NSAPI (mandatory) */
2349 if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
2350 gsn->missing++;
2351 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2352 "Missing mandatory information field");
2353 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2354 GTPCAUSE_MAN_IE_MISSING, teardown);
2357 /* Find the context in question */
2358 if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
2359 gsn->err_unknownpdp++;
2360 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2361 "Unknown PDP context");
2362 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
2363 GTPCAUSE_NON_EXIST, teardown);
2366 /* Teardown (conditional) */
2367 gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
2369 if (!teardown) {
2370 for (n=0; n< PDP_MAXNSAPI; n++)
2371 if (linked_pdp->secondary_tei[n]) count++;
2372 if (count <= 1) {
2373 return 0; /* 29.060 7.3.5 Ignore message */
2378 return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
2379 pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
2383 /* Handle Delete PDP Context Response */
2384 int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
2385 struct sockaddr_in *peer,
2386 void *pack, unsigned len) {
2387 union gtpie_member *ie[GTPIE_SIZE];
2388 uint8_t cause;
2389 void *cbp = NULL;
2390 uint8_t type = 0;
2391 int hlen = get_hlen(pack);
2393 /* Remove packet from queue */
2394 if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
2396 /* Decode information elements */
2397 if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
2398 gsn->invalid++;
2399 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2400 "Invalid message format");
2401 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
2402 return EOF;
2405 /* Extract cause value (mandatory) */
2406 if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
2407 gsn->missing++;
2408 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2409 "Missing mandatory information field");
2410 if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
2411 return EOF;
2414 /* Check the cause value (again) */
2415 if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
2416 gsn->err_cause++;
2417 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2418 "Unexpected cause value received: %d", cause);
2419 if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
2420 return EOF;
2423 /* Callback function to notify application */
2424 if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
2426 return 0;
2429 /* Send Error Indication (response to a GPDU message */
2430 int gtp_error_ind_resp(struct gsn_t *gsn, int version,
2431 struct sockaddr_in *peer, int fd,
2432 void *pack, unsigned len)
2434 union gtp_packet packet;
2435 unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
2437 return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
2438 get_seq(pack), get_tid(pack));
2441 /* Handle Error Indication */
2442 int gtp_error_ind_conf(struct gsn_t *gsn, int version,
2443 struct sockaddr_in *peer,
2444 void *pack, unsigned len) {
2445 struct pdp_t *pdp;
2447 /* Find the context in question */
2448 if (pdp_tidget(&pdp, ((union gtp_packet*)pack)->gtp0.h.tid)) {
2449 gsn->err_unknownpdp++;
2450 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2451 "Unknown PDP context");
2452 return EOF;
2455 gsn->err_unknownpdp++; /* TODO: Change counter */
2456 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2457 "Received Error Indication");
2459 if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
2460 pdp_freepdp(pdp);
2461 return 0;
2464 int gtp_gpdu_ind(struct gsn_t *gsn, int version,
2465 struct sockaddr_in *peer, int fd,
2466 void *pack, unsigned len) {
2468 int hlen = GTP1_HEADER_SIZE_SHORT;
2470 /* Need to include code to verify packet src and dest addresses */
2471 struct pdp_t *pdp;
2473 if (version == 0) {
2474 if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet*)pack)->gtp0.h.flow))) {
2475 gsn->err_unknownpdp++;
2476 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2477 "Unknown PDP context");
2478 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2480 hlen = GTP0_HEADER_SIZE;
2482 else if (version == 1) {
2483 if (pdp_getgtp1(&pdp, ntoh32(((union gtp_packet*)pack)->gtp1l.h.tei))) {
2484 gsn->err_unknownpdp++;
2485 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2486 "Unknown PDP context");
2487 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2490 /* Is this a long or a short header ? */
2491 if (((union gtp_packet*)pack)->gtp1l.h.flags & 0x07)
2492 hlen = GTP1_HEADER_SIZE_LONG;
2493 else
2494 hlen = GTP1_HEADER_SIZE_SHORT;
2496 else {
2497 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2498 "Unknown version");
2501 /* If the GPDU was not from the peer GSN tell him to delete context */
2502 if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
2503 gsn->err_unknownpdp++;
2504 gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
2505 "Unknown PDP context");
2506 return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
2509 /* Callback function */
2510 if (gsn->cb_data_ind !=0)
2511 return gsn->cb_data_ind(pdp, pack+hlen, len-hlen);
2513 return 0;
2518 /* Receives GTP packet and sends off for further processing
2519 * Function will check the validity of the header. If the header
2520 * is not valid the packet is either dropped or a version not
2521 * supported is returned to the peer.
2522 * TODO: Need to decide on return values! */
2523 int gtp_decaps0(struct gsn_t *gsn)
2525 unsigned char buffer[PACKET_MAX];
2526 struct sockaddr_in peer;
2527 size_t peerlen;
2528 int status;
2529 struct gtp0_header *pheader;
2530 int version = 0; /* GTP version should be determined from header!*/
2531 int fd = gsn->fd0;
2533 /* TODO: Need strategy of userspace buffering and blocking */
2534 /* Currently read is non-blocking and send is blocking. */
2535 /* This means that the program have to wait for busy send calls...*/
2537 while (1) { /* Loop until no more to read */
2538 if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
2539 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2540 return -1;
2542 peerlen = sizeof(peer);
2543 if ((status =
2544 recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
2545 (struct sockaddr *) &peer, &peerlen)) < 0 ) {
2546 if (errno == EAGAIN) return 0;
2547 gsn->err_readfrom++;
2548 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");
2549 return -1;
2552 /* Need at least 1 byte in order to check version */
2553 if (status < (1)) {
2554 gsn->empty++;
2555 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2556 "Discarding packet - too small");
2557 continue;
2560 pheader = (struct gtp0_header *) (buffer);
2562 /* Version should be gtp0 (or earlier) */
2563 /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
2564 /* GTP 0 messages. If other version message is received we reply that we */
2565 /* only support version 0, implying that this is the only version */
2566 /* supported on this port */
2567 if (((pheader->flags & 0xe0) > 0x00)) {
2568 gsn->unsup++;
2569 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2570 "Unsupported GTP version");
2571 gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
2572 continue;
2575 /* Check length of gtp0 packet */
2576 if (status < GTP0_HEADER_SIZE) {
2577 gsn->tooshort++;
2578 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2579 "GTP0 packet too short");
2580 continue; /* Silently discard 29.60: 11.1.2 */
2583 /* Check packet length field versus length of packet */
2584 if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
2585 gsn->tooshort++;
2586 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2587 "GTP packet length field does not match actual length");
2588 continue; /* Silently discard */
2591 if ((gsn->mode == GTP_MODE_GGSN) &&
2592 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2593 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2594 (pheader->type == GTP_DELETE_PDP_RSP))) {
2595 gsn->unexpect++;
2596 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2597 "Unexpected GTP Signalling Message");
2598 continue; /* Silently discard 29.60: 11.1.4 */
2601 if ((gsn->mode == GTP_MODE_SGSN) &&
2602 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2603 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2604 (pheader->type == GTP_DELETE_PDP_REQ))) {
2605 gsn->unexpect++;
2606 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2607 "Unexpected GTP Signalling Message");
2608 continue; /* Silently discard 29.60: 11.1.4 */
2611 switch (pheader->type) {
2612 case GTP_ECHO_REQ:
2613 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2614 break;
2615 case GTP_ECHO_RSP:
2616 gtp_echo_conf(gsn, version, &peer, buffer, status);
2617 break;
2618 case GTP_NOT_SUPPORTED:
2619 gtp_unsup_ind(gsn, &peer, buffer, status);
2620 break;
2621 case GTP_CREATE_PDP_REQ:
2622 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer, status);
2623 break;
2624 case GTP_CREATE_PDP_RSP:
2625 gtp_create_pdp_conf(gsn, version, &peer, buffer, status);
2626 break;
2627 case GTP_UPDATE_PDP_REQ:
2628 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer, status);
2629 break;
2630 case GTP_UPDATE_PDP_RSP:
2631 gtp_update_pdp_conf(gsn, version, &peer, buffer, status);
2632 break;
2633 case GTP_DELETE_PDP_REQ:
2634 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer, status);
2635 break;
2636 case GTP_DELETE_PDP_RSP:
2637 gtp_delete_pdp_conf(gsn, version, &peer, buffer, status);
2638 break;
2639 case GTP_ERROR:
2640 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2641 break;
2642 case GTP_GPDU:
2643 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2644 break;
2645 default:
2646 gsn->unknown++;
2647 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2648 "Unknown GTP message type received");
2649 break;
2655 int gtp_decaps1c(struct gsn_t *gsn)
2657 unsigned char buffer[PACKET_MAX];
2658 struct sockaddr_in peer;
2659 size_t peerlen;
2660 int status;
2661 struct gtp1_header_short *pheader;
2662 int version = 1; /* TODO GTP version should be determined from header!*/
2663 int fd = gsn->fd1c;
2665 /* TODO: Need strategy of userspace buffering and blocking */
2666 /* Currently read is non-blocking and send is blocking. */
2667 /* This means that the program have to wait for busy send calls...*/
2669 while (1) { /* Loop until no more to read */
2670 if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
2671 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2672 return -1;
2674 peerlen = sizeof(peer);
2675 if ((status =
2676 recvfrom(fd, buffer, sizeof(buffer), 0,
2677 (struct sockaddr *) &peer, &peerlen)) < 0 ) {
2678 if (errno == EAGAIN) return 0;
2679 gsn->err_readfrom++;
2680 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");
2681 return -1;
2684 /* Need at least 1 byte in order to check version */
2685 if (status < (1)) {
2686 gsn->empty++;
2687 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2688 "Discarding packet - too small");
2689 continue;
2692 pheader = (struct gtp1_header_short *) (buffer);
2694 /* Version must be no larger than GTP 1 */
2695 if (((pheader->flags & 0xe0) > 0x20)) {
2696 gsn->unsup++;
2697 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2698 "Unsupported GTP version");
2699 gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
2700 /*29.60: 11.1.1*/
2701 continue;
2704 /* Version must be at least GTP 1 */
2705 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2706 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2707 /* the message */
2708 if (((pheader->flags & 0xe0) < 0x20)) {
2709 gsn->unsup++;
2710 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2711 "Unsupported GTP version");
2712 continue;
2715 /* Check packet flag field */
2716 if (((pheader->flags & 0xf7) != 0x32)) {
2717 gsn->unsup++;
2718 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2719 "Unsupported packet flag");
2720 continue;
2723 /* Check length of packet */
2724 if (status < GTP1_HEADER_SIZE_LONG) {
2725 gsn->tooshort++;
2726 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2727 "GTP packet too short");
2728 continue; /* Silently discard 29.60: 11.1.2 */
2731 /* Check packet length field versus length of packet */
2732 if (status != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2733 gsn->tooshort++;
2734 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2735 "GTP packet length field does not match actual length");
2736 continue; /* Silently discard */
2739 /* Check for extension headers */
2740 /* TODO: We really should cycle through the headers and determine */
2741 /* if any have the comprehension required flag set */
2742 if (((pheader->flags & 0x04) != 0x00)) {
2743 gsn->unsup++;
2744 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2745 "Unsupported extension header");
2746 gtp_extheader_req(gsn, version, &peer, fd, buffer, status);
2748 continue;
2751 if ((gsn->mode == GTP_MODE_GGSN) &&
2752 ((pheader->type == GTP_CREATE_PDP_RSP) ||
2753 (pheader->type == GTP_UPDATE_PDP_RSP) ||
2754 (pheader->type == GTP_DELETE_PDP_RSP))) {
2755 gsn->unexpect++;
2756 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2757 "Unexpected GTP Signalling Message");
2758 continue; /* Silently discard 29.60: 11.1.4 */
2761 if ((gsn->mode == GTP_MODE_SGSN) &&
2762 ((pheader->type == GTP_CREATE_PDP_REQ) ||
2763 (pheader->type == GTP_UPDATE_PDP_REQ) ||
2764 (pheader->type == GTP_DELETE_PDP_REQ))) {
2765 gsn->unexpect++;
2766 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2767 "Unexpected GTP Signalling Message");
2768 continue; /* Silently discard 29.60: 11.1.4 */
2771 switch (pheader->type) {
2772 case GTP_ECHO_REQ:
2773 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2774 break;
2775 case GTP_ECHO_RSP:
2776 gtp_echo_conf(gsn, version, &peer, buffer, status);
2777 break;
2778 case GTP_NOT_SUPPORTED:
2779 gtp_unsup_ind(gsn, &peer, buffer, status);
2780 break;
2781 case GTP_SUPP_EXT_HEADER:
2782 gtp_extheader_ind(gsn, &peer, buffer, status);
2783 break;
2784 case GTP_CREATE_PDP_REQ:
2785 gtp_create_pdp_ind(gsn, version, &peer, fd, buffer, status);
2786 break;
2787 case GTP_CREATE_PDP_RSP:
2788 gtp_create_pdp_conf(gsn, version, &peer, buffer, status);
2789 break;
2790 case GTP_UPDATE_PDP_REQ:
2791 gtp_update_pdp_ind(gsn, version, &peer, fd, buffer, status);
2792 break;
2793 case GTP_UPDATE_PDP_RSP:
2794 gtp_update_pdp_conf(gsn, version, &peer, buffer, status);
2795 break;
2796 case GTP_DELETE_PDP_REQ:
2797 gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer, status);
2798 break;
2799 case GTP_DELETE_PDP_RSP:
2800 gtp_delete_pdp_conf(gsn, version, &peer, buffer, status);
2801 break;
2802 case GTP_ERROR:
2803 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2804 break;
2805 default:
2806 gsn->unknown++;
2807 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2808 "Unknown GTP message type received");
2809 break;
2814 int gtp_decaps1u(struct gsn_t *gsn)
2816 unsigned char buffer[PACKET_MAX];
2817 struct sockaddr_in peer;
2818 size_t peerlen;
2819 int status;
2820 struct gtp1_header_short *pheader;
2821 int version = 1; /* GTP version should be determined from header!*/
2822 int fd = gsn->fd1u;
2824 /* TODO: Need strategy of userspace buffering and blocking */
2825 /* Currently read is non-blocking and send is blocking. */
2826 /* This means that the program have to wait for busy send calls...*/
2828 while (1) { /* Loop until no more to read */
2829 if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
2830 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
2831 return -1;
2833 peerlen = sizeof(peer);
2834 if ((status =
2835 recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
2836 (struct sockaddr *) &peer, &peerlen)) < 0 ) {
2837 if (errno == EAGAIN) return 0;
2838 gsn->err_readfrom++;
2839 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");
2840 return -1;
2843 /* Need at least 1 byte in order to check version */
2844 if (status < (1)) {
2845 gsn->empty++;
2846 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2847 "Discarding packet - too small");
2848 continue;
2851 pheader = (struct gtp1_header_short *) (buffer);
2853 /* Version must be no larger than GTP 1 */
2854 if (((pheader->flags & 0xe0) > 0x20)) {
2855 gsn->unsup++;
2856 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2857 "Unsupported GTP version");
2858 gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status);/*29.60: 11.1.1*/
2859 continue;
2862 /* Version must be at least GTP 1 */
2863 /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
2864 /* GTP 1 messages. If GTP 0 message is received we silently discard */
2865 /* the message */
2866 if (((pheader->flags & 0xe0) < 0x20)) {
2867 gsn->unsup++;
2868 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2869 "Unsupported GTP version");
2870 continue;
2873 /* Check packet flag field (allow both with and without sequence number)*/
2874 if (((pheader->flags & 0xf5) != 0x30)) {
2875 gsn->unsup++;
2876 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2877 "Unsupported packet flag");
2878 continue;
2881 /* Check length of packet */
2882 if (status < GTP1_HEADER_SIZE_SHORT) {
2883 gsn->tooshort++;
2884 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2885 "GTP packet too short");
2886 continue; /* Silently discard 29.60: 11.1.2 */
2889 /* Check packet length field versus length of packet */
2890 if (status != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
2891 gsn->tooshort++;
2892 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2893 "GTP packet length field does not match actual length");
2894 continue; /* Silently discard */
2897 /* Check for extension headers */
2898 /* TODO: We really should cycle through the headers and determine */
2899 /* if any have the comprehension required flag set */
2900 if (((pheader->flags & 0x04) != 0x00)) {
2901 gsn->unsup++;
2902 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2903 "Unsupported extension header");
2904 gtp_extheader_req(gsn, version, &peer, fd, buffer, status);
2906 continue;
2909 switch (pheader->type) {
2910 case GTP_ECHO_REQ:
2911 gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
2912 break;
2913 case GTP_ECHO_RSP:
2914 gtp_echo_conf(gsn, version, &peer, buffer, status);
2915 break;
2916 case GTP_SUPP_EXT_HEADER:
2917 gtp_extheader_ind(gsn, &peer, buffer, status);
2918 break;
2919 case GTP_ERROR:
2920 gtp_error_ind_conf(gsn, version, &peer, buffer, status);
2921 break;
2922 /* Supported header extensions */
2923 case GTP_GPDU:
2924 gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
2925 break;
2926 default:
2927 gsn->unknown++;
2928 gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
2929 "Unknown GTP message type received");
2930 break;
2935 int gtp_data_req(struct gsn_t *gsn, struct pdp_t* pdp,
2936 void *pack, unsigned len)
2938 union gtp_packet packet;
2939 struct sockaddr_in addr;
2940 int fd;
2941 int length;
2943 memset(&addr, 0, sizeof(addr));
2944 addr.sin_family = AF_INET;
2945 #if defined(__FreeBSD__) || defined(__APPLE__)
2946 addr.sin_len = sizeof(addr);
2947 #endif
2949 memcpy(&addr.sin_addr, pdp->gsnru.v,pdp->gsnru.l); /* TODO range check */
2951 if (pdp->version == 0) {
2953 length = GTP0_HEADER_SIZE+len;
2954 addr.sin_port = htons(GTP0_PORT);
2955 fd = gsn->fd0;
2957 get_default_gtp(0, GTP_GPDU, &packet);
2958 packet.gtp0.h.length = hton16(len);
2959 packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
2960 packet.gtp0.h.flow = hton16(pdp->flru);
2961 packet.gtp0.h.tid = (pdp->imsi & 0x0fffffffffffffffull) + ((uint64_t)pdp->nsapi << 60);
2963 if (len > sizeof (union gtp_packet) - sizeof(struct gtp0_header)) {
2964 gsn->err_memcpy++;
2965 gtp_err(LOG_ERR, __FILE__, __LINE__,
2966 "Memcpy failed: %d > %d", len,
2967 sizeof (union gtp_packet) - sizeof(struct gtp0_header));
2968 return EOF;
2970 memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
2972 else if (pdp->version == 1) {
2974 length = GTP1_HEADER_SIZE_LONG+len;
2975 addr.sin_port = htons(GTP1U_PORT);
2976 fd = gsn->fd1u;
2978 get_default_gtp(1, GTP_GPDU, &packet);
2979 packet.gtp1l.h.length = hton16(len-GTP1_HEADER_SIZE_SHORT+
2980 GTP1_HEADER_SIZE_LONG);
2981 packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
2982 packet.gtp1l.h.tei = hton32(pdp->teid_gn);
2984 if (len > sizeof (union gtp_packet) - sizeof(struct gtp1_header_long)) {
2985 gsn->err_memcpy++;
2986 gtp_err(LOG_ERR, __FILE__, __LINE__,
2987 "Memcpy failed: %d > %d", len,
2988 sizeof (union gtp_packet) - sizeof(struct gtp0_header));
2989 return EOF;
2991 memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
2993 else {
2994 gtp_err(LOG_ERR, __FILE__, __LINE__,
2995 "Unknown version");
2996 return EOF;
2999 if (fcntl(fd, F_SETFL, 0)) {
3000 gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
3001 return -1;
3004 if (sendto(fd, &packet, length, 0,
3005 (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3006 gsn->err_sendto++;
3007 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));
3008 return EOF;
3010 return 0;
3014 /* ***********************************************************
3015 * Conversion functions
3016 *************************************************************/
3018 int char2ul_t(char* src, struct ul_t dst) {
3019 dst.l = strlen(src)+1;
3020 dst.v = malloc(dst.l);
3021 dst.v[0] = dst.l - 1;
3022 memcpy(&dst.v[1], src, dst.v[0]);
3023 return 0;
3026 /* ***********************************************************
3027 * IP address conversion functions
3028 * There exist several types of address representations:
3029 * - eua: End User Address. (29.060, 7.7.27, message type 128)
3030 * Used for signalling address to mobile station. Supports IPv4
3031 * IPv6 x.25 etc. etc.
3032 * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
3033 * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
3034 * - in_addr: IPv4 address struct.
3035 * - sockaddr_in: Socket API representation of IP address and
3036 * port number.
3037 *************************************************************/
3039 int ipv42eua(struct ul66_t *eua, struct in_addr *src) {
3040 eua->v[0] = 0xf1; /* IETF */
3041 eua->v[1] = 0x21; /* IPv4 */
3042 if (src) {
3043 eua->l = 6;
3044 memcpy(&eua->v[2], src, 4);
3046 else
3048 eua->l = 2;
3050 return 0;
3053 int eua2ipv4(struct in_addr *dst, struct ul66_t *eua) {
3054 if ((eua->l != 6) ||
3055 (eua->v[0] != 0xf1) ||
3056 (eua->v[1] = 0x21))
3057 return -1; /* Not IPv4 address*/
3058 memcpy(dst, &eua->v[2], 4);
3059 return 0;
3062 int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna) {
3063 memset(dst, 0, sizeof(struct in_addr));
3064 if (gsna->l != 4) return EOF; /* Return if not IPv4 */
3065 memcpy(dst, gsna->v, gsna->l);
3066 return 0;
3069 int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src) {
3070 memset(gsna, 0, sizeof(struct ul16_t));
3071 gsna->l = 4;
3072 memcpy(gsna->v, src, gsna->l);
3073 return 0;