2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002, 2003, 2004 Mondru AB.
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.
13 * gtp.c: Contains all GTP functionality. Should be able to handle multiple
14 * tunnels in the same program.
17 * - Do we need to handle fragmentation?
25 #include "../config.h"
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
46 #include <arpa/inet.h>
48 /* #include <stdint.h> ISO C99 types */
56 /* Error reporting functions */
58 void gtp_err(int priority
, char *filename
, int linenum
, char *fmt
, ...) {
60 char buf
[ERRMSG_SIZE
];
63 vsnprintf(buf
, ERRMSG_SIZE
, fmt
, 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
, ...) {
73 char buf
[ERRMSG_SIZE
];
74 char buf2
[ERRMSG_SIZE
];
79 vsnprintf(buf
, ERRMSG_SIZE
, fmt
, 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
),
87 buf2
[ERRMSG_SIZE
-1] = 0;
89 for(n
=0; n
<len
; n
++) {
90 if ((pos
+4)<ERRMSG_SIZE
) {
91 sprintf((buf2
+pos
), " %02hhx", ((unsigned char*)pack
)[n
]);
97 syslog(pri
, "%s: %d: %s. %s", fn
, ln
, buf
, buf2
);
106 const char* gtp_version()
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
);
125 extern int gtp_fd(struct gsn_t
*gsn
) {
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
;
140 int gtp_set_cb_extheader_ind(struct gsn_t
*gsn
,
141 int (*cb
) (struct sockaddr_in
*peer
)) {
142 gsn
->cb_extheader_ind
= cb
;
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
;
156 int gtp_set_cb_conf(struct gsn_t
*gsn
,
157 int (*cb
) (int type
, int cause
,
158 struct pdp_t
* pdp
, void *cbp
)) {
163 extern int gtp_set_cb_data_ind(struct gsn_t
*gsn
,
164 int (*cb_data_ind
) (struct pdp_t
* pdp
,
168 gsn
->cb_data_ind
= cb_data_ind
;
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
;
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
;
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 */
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
;
206 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown GTP packet version");
213 * Get sequence number of a packet.
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
);
225 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown packet flag");
232 * Get tunnel identifier of a packet.
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
;
246 * Get the header length of a packet.
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
;
261 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown packet flag");
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
);
281 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown packet flag");
287 int print_packet(void *packet
, unsigned len
)
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");
299 char* snprint_packet(struct gsn_t
*gsn
, struct sockaddr_in
*peer
,
300 void *pack
, unsigned len
, char *buf
, int size
) {
303 snprintf(buf
, size
, "Packet from %s:%u, length: %d, content:",
304 inet_ntoa(peer
->sin_addr
),
305 ntohs(peer
->sin_port
),
309 for(n
=0; n
<len
; n
++) {
311 sprintf((buf
+pos
), " %02hhx", ((unsigned char*)pack
)[n
]);
320 /* ***********************************************************
321 * Reliable delivery of signalling messages
323 * Sequence numbers are used for both signalling messages and
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
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.
383 * Send off a signalling message with appropiate sequence
384 * number. Store packet in queue.
386 * Remove an incoming confirmation from the queue
388 * Send off a response to a request. Use the same sequence
389 * number in the response as in the request.
391 * Send off a notification message. This is neither a request nor
392 * a response. Both TEI and SEQ are zero.
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
;
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
);
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
);
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
);
423 packet
->gtp0
.h
.flow
=hton16(pdp
->flrc
);
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
);
434 packet
->gtp1l
.h
.tei
=hton32(pdp
->teic_gn
);
437 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown packet flag");
441 if (sendto(fd
, packet
, len
, 0,
442 (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
444 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd
, (unsigned long) &packet
, len
, strerror(errno
));
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");
454 memcpy(&qmsg
->p
, packet
, sizeof(union gtp_packet
));
456 qmsg
->timeout
= time(NULL
) + 3; /* When to timeout */
457 qmsg
->retrans
= 0; /* No retransmissions so far */
459 qmsg
->type
= ntoh8(packet
->gtp0
.h
.type
);
462 gsn
->seq_next
++; /* Count up this time */
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
) {
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
);
480 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, peer
, packet
, len
,
481 "Unknown GTP packet version");
485 if (queue_freemsg_seq(gsn
->queue_req
, peer
, seq
, type
, cbp
)) {
487 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, peer
, packet
, len
,
488 "Confirmation packet not found in queue");
495 int gtp_retrans(struct gsn_t
*gsn
) {
496 /* Retransmit any outstanding packets */
497 /* Remove from queue if maxretrans exceeded */
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
);
511 if (sendto(qmsg
->fd
, &qmsg
->p
, qmsg
->l
, 0,
512 (struct sockaddr
*) &qmsg
->peer
, sizeof(struct sockaddr_in
)) < 0) {
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;
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
);
532 int gtp_retranstimeout(struct gsn_t
*gsn
, struct timeval
*timeout
) {
536 if (queue_getfirst(gsn
->queue_req
, &qmsg
)) {
537 timeout
->tv_sec
= 10;
538 timeout
->tv_usec
= 0;
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*/
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
) {
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
);
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
);
573 packet
->gtp1l
.h
.tei
=hton32(pdp
->teic_gn
);
576 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown packet flag");
580 if (fcntl(fd
, F_SETFL
, 0)) {
581 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "fnctl()");
585 if (sendto(fd
, packet
, len
, 0,
586 (struct sockaddr
*) peer
, sizeof(struct sockaddr_in
)) < 0) {
588 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd
, (unsigned long) &packet
, len
, strerror(errno
));
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");
598 memcpy(&qmsg
->p
, packet
, sizeof(union gtp_packet
));
600 qmsg
->timeout
= time(NULL
) + 60; /* When to timeout */
601 qmsg
->retrans
= 0; /* No retransmissions so far */
609 int gtp_notification(struct gsn_t
*gsn
, int version
,
610 union gtp_packet
*packet
, int len
,
611 struct sockaddr_in
*peer
, int fd
,
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 */
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
);
635 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown packet flag");
639 if (fcntl(fd
, F_SETFL
, 0)) {
640 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "fnctl()");
644 if (sendto(fd
, packet
, len
, 0,
645 (struct sockaddr
*) &addr
, sizeof(struct sockaddr_in
)) < 0) {
647 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd
, (unsigned long) &packet
, len
, strerror(errno
));
653 int gtp_dublicate(struct gsn_t
*gsn
, int version
,
654 struct sockaddr_in
*peer
, uint16_t seq
) {
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()");
666 if (sendto(qmsg
->fd
, &qmsg
->p
, qmsg
->l
, 0,
667 (struct sockaddr
*) peer
, sizeof(struct sockaddr_in
)) < 0) {
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
));
676 /* Perform restoration and recovery error handling as described in 29.060 */
677 static void log_restart(struct gsn_t
*gsn
) {
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
));
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
);
697 fscanf(f
, "%d", &counter
);
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
));
712 fprintf(f
, "%d\n", gsn
->restart_counter
);
714 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "fclose failed: Error = %s", strerror(errno
));
721 int gtp_new(struct gsn_t
**gsn
, char *statedir
, struct in_addr
*listen
,
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
;
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 */
743 /* Initialise call back functions */
744 (*gsn
)->cb_create_context_ind
= 0;
745 (*gsn
)->cb_delete_context
= 0;
746 (*gsn
)->cb_unsup_ind
= 0;
748 (*gsn
)->cb_data_ind
= 0;
750 /* Store function parameters */
751 (*gsn
)->gsnc
= *listen
;
752 (*gsn
)->gsnu
= *listen
;
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
));
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
);
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
));
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
));
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
);
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
));
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
));
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
);
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
));
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
);
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
854 * For response messages we need to be able to respond to
855 * the relevant src port even if it is locally allocated by
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
;
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
)) {
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
);
919 if (gtpie_gettv1(ie
, GTPIE_RECOVERY
, 0, &recovery
)) {
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
);
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
);
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
,
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
);
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
;
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
),
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
);
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
1005 *************************************************************/
1007 /* API: Send Create PDP Context Request */
1008 extern int gtp_create_context_req(struct gsn_t
*gsn
, struct pdp_t
*pdp
,
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");
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
,
1045 if (pdp
->version
== 0) {
1046 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_DI
,
1048 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_C
,
1052 if (pdp
->version
== 1) {
1053 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_DI
,
1056 if (!pdp
->teic_confirmed
)
1057 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_C
,
1060 gtpie_tv1(&packet
, &length
, GTP_MAX
, GTPIE_NSAPI
,
1063 if (pdp
->secondary
) /* Secondary PDP Context Activation Procedure */
1064 gtpie_tv1(&packet
, &length
, GTP_MAX
, GTPIE_NSAPI
,
1067 if (pdp
->cch_pdp
) /* Only include charging if flags are set */
1068 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_CHARGING_C
,
1073 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1075 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
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 */
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
);
1119 gtp_req(gsn
, pdp
->version
, pdp
, &packet
, length
, &pdp
->hisaddr0
, cbp
);
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
) {
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
;
1146 /* Send Create PDP Context Response */
1147 int gtp_create_pdp_resp(struct gsn_t
*gsn
, int version
, struct pdp_t
*pdp
,
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
) {
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
,
1162 gtpie_tv1(&packet
, &length
, GTP_MAX
, GTPIE_RECOVERY
,
1163 gsn
->restart_counter
);
1166 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_DI
,
1168 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_C
,
1173 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_DI
,
1175 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_C
,
1179 /* TODO: We use teic_own as charging ID */
1180 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_CHARGING_ID
,
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
);
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
];
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;
1224 memset(pdp
, 0, sizeof(struct pdp_t
));
1227 pdp
->imsi
= ((union gtp_packet
*)pack
)->gtp0
.h
.tid
& 0x0fffffffffffffffull
;
1228 pdp
->nsapi
= (((union gtp_packet
*)pack
)->gtp0
.h
.tid
& 0xf000000000000000ull
) >> 60;
1232 pdp
->sa_peer
= *peer
;
1234 pdp
->version
= version
;
1236 /* Decode information elements */
1237 if (gtpie_decaps(ie
, version
, pack
+hlen
, len
-hlen
)) {
1239 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, peer
, pack
, len
,
1240 "Invalid message format");
1244 return gtp_create_pdp_resp(gsn
, version
, pdp
, GTPCAUSE_INVALID_MESSAGE
);
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
))) {
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
) {
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
;
1282 } /* if (version == 1) */
1285 if (gtpie_gettv0(ie
, GTPIE_QOS_PROFILE0
, 0,
1286 pdp
->qos_req0
, sizeof(pdp
->qos_req0
))) {
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
))) {
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
))) {
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
);
1324 if (gtpie_gettv2(ie
, GTPIE_FL_DI
, 0, &pdp
->flru
)) {
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
)) {
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
);
1343 /* TEID (mandatory) */
1344 if (gtpie_gettv4(ie
, GTPIE_TEI_DI
, 0, &pdp
->teid_gn
)) {
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
)) {
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
)) {
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
))) {
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
);
1391 if (gtpie_gettlv(ie
, GTPIE_APN
, 0, &pdp
->apn_req
.l
,
1392 &pdp
->apn_req
.v
, sizeof(pdp
->apn_req
.v
))) {
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
))) {
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
))) {
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
))) {
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
);
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
))) {
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
))) {
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 */
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
);
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
) {
1539 union gtpie_member
*ie
[GTPIE_SIZE
];
1540 uint8_t cause
, recovery
;
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
);
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
)) {
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); */
1571 /* Extract cause value (mandatory) */
1572 if (gtpie_gettv1(ie
, GTPIE_CAUSE
, 0, &cause
)) {
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); */
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
) {
1596 if (gtpie_gettv0(ie
, GTPIE_QOS_PROFILE0
, 0,
1597 &pdp
->qos_neg0
, sizeof(pdp
->qos_neg0
))) {
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); */
1608 if (gtpie_gettv1(ie
, GTPIE_REORDER
, 0, &pdp
->reorder
)) {
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); */
1619 if (gtpie_gettv2(ie
, GTPIE_FL_DI
, 0, &pdp
->flru
)) {
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); */
1629 if (gtpie_gettv2(ie
, GTPIE_FL_C
, 0, &pdp
->flrc
)) {
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); */
1641 if (gtpie_gettv4(ie
, GTPIE_TEI_DI
, 0, &pdp
->teid_gn
)) {
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); */
1651 if (gtpie_gettv4(ie
, GTPIE_TEI_C
, 0, &pdp
->teic_gn
)) {
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); */
1662 if (gtpie_gettv4(ie
, GTPIE_CHARGING_ID
, 0, &pdp
->cid
)) {
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
))) {
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); */
1682 if (gtpie_gettlv(ie
, GTPIE_GSN_ADDR
, 0, &pdp
->gsnrc
.l
,
1683 &pdp
->gsnrc
.v
, sizeof(pdp
->gsnrc
.v
))) {
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); */
1693 if (gtpie_gettlv(ie
, GTPIE_GSN_ADDR
, 1, &pdp
->gsnru
.l
,
1694 &pdp
->gsnru
.v
, sizeof(pdp
->gsnru
.v
))) {
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); */
1705 if (gtpie_gettlv(ie
, GTPIE_QOS_PROFILE
, 0, &pdp
->qos_neg
.l
,
1706 &pdp
->qos_neg
.v
, sizeof(pdp
->qos_neg
.v
))) {
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); */
1719 if (gsn
->cb_conf
) gsn
->cb_conf(type
, cause
, pdp
, cbp
);
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
,
1746 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_C
,
1750 if (pdp
->version
== 1) {
1751 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_DI
,
1754 if (!pdp
->teic_confirmed
)
1755 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_C
,
1759 gtpie_tv1(&packet
, &length
, GTP_MAX
, GTPIE_NSAPI
,
1763 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
1765 gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
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
);
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
) {
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
);
1822 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_DI
,
1824 gtpie_tv2(&packet
, &length
, GTP_MAX
, GTPIE_FL_C
,
1829 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_DI
,
1832 if (!pdp
->teic_confirmed
)
1833 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_TEI_C
,
1837 /* TODO we use teid_own as charging ID address */
1838 gtpie_tv4(&packet
, &length
, GTP_MAX
, GTPIE_CHARGING_ID
,
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
);
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
) {
1867 struct pdp_t pdp_backup
;
1868 union gtpie_member
* ie
[GTPIE_SIZE
];
1871 uint16_t seq
= get_seq(pack
);
1872 int hlen
= get_hlen(pack
);
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
)) {
1886 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, peer
, pack
, len
,
1887 "Invalid message format");
1891 return gtp_update_pdp_resp(gsn
, version
, peer
, fd
, pack
, len
,
1892 NULL
, GTPCAUSE_INVALID_MESSAGE
);
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 */
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
)) {
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
);
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
);
1945 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown version");
1949 /* Make a backup copy in case anything is wrong */
1950 memcpy(&pdp_backup
, pdp
, sizeof(pdp_backup
));
1953 if (gtpie_gettv0(ie
, GTPIE_QOS_PROFILE0
, 0,
1954 pdp
->qos_req0
, sizeof(pdp
->qos_req0
))) {
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 */
1970 if (gtpie_gettv2(ie
, GTPIE_FL_DI
, 0, &pdp
->flru
)) {
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
)) {
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
);
1991 /* TEID (mandatory) */
1992 if (gtpie_gettv4(ie
, GTPIE_TEI_DI
, 0, &pdp
->teid_gn
)) {
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
)) {
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))) {
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);
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
))) {
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
))) {
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
);
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
))) {
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
))) {
2076 /* Confirm to peer that things were "successful" */
2077 return gtp_update_pdp_resp(gsn
, version
, peer
, fd
, pack
, len
, pdp
,
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
) {
2087 union gtpie_member
*ie
[GTPIE_SIZE
];
2088 uint8_t cause
, recovery
;
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
);
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
)) {
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); */
2118 /* Extract cause value (mandatory) */
2119 if (gtpie_gettv1(ie
, GTPIE_CAUSE
, 0, &cause
)) {
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); */
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); */
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))) {
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); */
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
,
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
;
2191 if (gsna2in_addr(&addr
, &pdp
->gsnrc
)) {
2193 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "GSN address conversion failed");
2197 if (pdp_getgtp1(&linked_pdp
, pdp
->teic_own
)) {
2198 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "Unknown linked PDP context");
2203 for (n
=0; n
< PDP_MAXNSAPI
; n
++)
2204 if (linked_pdp
->secondary_tei
[n
]) count
++;
2206 gtp_err(LOG_ERR
, __FILE__
, __LINE__
,
2207 "Must use teardown for last context");
2212 if (pdp
->version
== 1) {
2214 gtpie_tv1(&packet
, &length
, GTP_MAX
, GTPIE_TEARDOWN
,
2217 gtpie_tv1(&packet
, &length
, GTP_MAX
, GTPIE_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");
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
);
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;
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
);
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");
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;
2296 } /* if (cause == GTPCAUSE_ACC_REQ) */
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
);
2313 uint8_t teardown
= 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 */
2335 /* Decode information elements */
2336 if (gtpie_decaps(ie
, version
, pack
+hlen
, len
-hlen
)) {
2338 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, peer
, pack
, len
,
2339 "Invalid message format");
2343 return gtp_delete_pdp_resp(gsn
, version
, peer
, fd
, pack
, len
, NULL
, NULL
,
2344 GTPCAUSE_INVALID_MESSAGE
, teardown
);
2348 /* NSAPI (mandatory) */
2349 if (gtpie_gettv1(ie
, GTPIE_NSAPI
, 0, &nsapi
)) {
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
);
2370 for (n
=0; n
< PDP_MAXNSAPI
; n
++)
2371 if (linked_pdp
->secondary_tei
[n
]) count
++;
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
];
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
)) {
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
);
2405 /* Extract cause value (mandatory) */
2406 if (gtpie_gettv1(ie
, GTPIE_CAUSE
, 0, &cause
)) {
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
);
2414 /* Check the cause value (again) */
2415 if ((GTPCAUSE_ACC_REQ
!= cause
) && (GTPCAUSE_NON_EXIST
!= 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
);
2423 /* Callback function to notify application */
2424 if (gsn
->cb_conf
) gsn
->cb_conf(type
, cause
, NULL
, cbp
);
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
) {
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");
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
);
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 */
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
;
2494 hlen
= GTP1_HEADER_SIZE_SHORT
;
2497 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, peer
, pack
, len
,
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
);
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
;
2529 struct gtp0_header
*pheader
;
2530 int version
= 0; /* GTP version should be determined from header!*/
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()");
2542 peerlen
= sizeof(peer
);
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");
2552 /* Need at least 1 byte in order to check version */
2555 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2556 "Discarding packet - too small");
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)) {
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 */
2575 /* Check length of gtp0 packet */
2576 if (status
< GTP0_HEADER_SIZE
) {
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
)) {
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
))) {
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
))) {
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
) {
2613 gtp_echo_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2616 gtp_echo_conf(gsn
, version
, &peer
, buffer
, status
);
2618 case GTP_NOT_SUPPORTED
:
2619 gtp_unsup_ind(gsn
, &peer
, buffer
, status
);
2621 case GTP_CREATE_PDP_REQ
:
2622 gtp_create_pdp_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2624 case GTP_CREATE_PDP_RSP
:
2625 gtp_create_pdp_conf(gsn
, version
, &peer
, buffer
, status
);
2627 case GTP_UPDATE_PDP_REQ
:
2628 gtp_update_pdp_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2630 case GTP_UPDATE_PDP_RSP
:
2631 gtp_update_pdp_conf(gsn
, version
, &peer
, buffer
, status
);
2633 case GTP_DELETE_PDP_REQ
:
2634 gtp_delete_pdp_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2636 case GTP_DELETE_PDP_RSP
:
2637 gtp_delete_pdp_conf(gsn
, version
, &peer
, buffer
, status
);
2640 gtp_error_ind_conf(gsn
, version
, &peer
, buffer
, status
);
2643 gtp_gpdu_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2647 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2648 "Unknown GTP message type received");
2655 int gtp_decaps1c(struct gsn_t
*gsn
)
2657 unsigned char buffer
[PACKET_MAX
];
2658 struct sockaddr_in peer
;
2661 struct gtp1_header_short
*pheader
;
2662 int version
= 1; /* TODO GTP version should be determined from header!*/
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()");
2674 peerlen
= sizeof(peer
);
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");
2684 /* Need at least 1 byte in order to check version */
2687 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2688 "Discarding packet - too small");
2692 pheader
= (struct gtp1_header_short
*) (buffer
);
2694 /* Version must be no larger than GTP 1 */
2695 if (((pheader
->flags
& 0xe0) > 0x20)) {
2697 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2698 "Unsupported GTP version");
2699 gtp_unsup_req(gsn
, version
, &peer
, fd
, buffer
, status
);
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 */
2708 if (((pheader
->flags
& 0xe0) < 0x20)) {
2710 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2711 "Unsupported GTP version");
2715 /* Check packet flag field */
2716 if (((pheader
->flags
& 0xf7) != 0x32)) {
2718 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2719 "Unsupported packet flag");
2723 /* Check length of packet */
2724 if (status
< GTP1_HEADER_SIZE_LONG
) {
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
)) {
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)) {
2744 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2745 "Unsupported extension header");
2746 gtp_extheader_req(gsn
, version
, &peer
, fd
, buffer
, status
);
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
))) {
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
))) {
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
) {
2773 gtp_echo_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2776 gtp_echo_conf(gsn
, version
, &peer
, buffer
, status
);
2778 case GTP_NOT_SUPPORTED
:
2779 gtp_unsup_ind(gsn
, &peer
, buffer
, status
);
2781 case GTP_SUPP_EXT_HEADER
:
2782 gtp_extheader_ind(gsn
, &peer
, buffer
, status
);
2784 case GTP_CREATE_PDP_REQ
:
2785 gtp_create_pdp_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2787 case GTP_CREATE_PDP_RSP
:
2788 gtp_create_pdp_conf(gsn
, version
, &peer
, buffer
, status
);
2790 case GTP_UPDATE_PDP_REQ
:
2791 gtp_update_pdp_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2793 case GTP_UPDATE_PDP_RSP
:
2794 gtp_update_pdp_conf(gsn
, version
, &peer
, buffer
, status
);
2796 case GTP_DELETE_PDP_REQ
:
2797 gtp_delete_pdp_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2799 case GTP_DELETE_PDP_RSP
:
2800 gtp_delete_pdp_conf(gsn
, version
, &peer
, buffer
, status
);
2803 gtp_error_ind_conf(gsn
, version
, &peer
, buffer
, status
);
2807 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2808 "Unknown GTP message type received");
2814 int gtp_decaps1u(struct gsn_t
*gsn
)
2816 unsigned char buffer
[PACKET_MAX
];
2817 struct sockaddr_in peer
;
2820 struct gtp1_header_short
*pheader
;
2821 int version
= 1; /* GTP version should be determined from header!*/
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()");
2833 peerlen
= sizeof(peer
);
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");
2843 /* Need at least 1 byte in order to check version */
2846 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2847 "Discarding packet - too small");
2851 pheader
= (struct gtp1_header_short
*) (buffer
);
2853 /* Version must be no larger than GTP 1 */
2854 if (((pheader
->flags
& 0xe0) > 0x20)) {
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*/
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 */
2866 if (((pheader
->flags
& 0xe0) < 0x20)) {
2868 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2869 "Unsupported GTP version");
2873 /* Check packet flag field (allow both with and without sequence number)*/
2874 if (((pheader
->flags
& 0xf5) != 0x30)) {
2876 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2877 "Unsupported packet flag");
2881 /* Check length of packet */
2882 if (status
< GTP1_HEADER_SIZE_SHORT
) {
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
)) {
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)) {
2902 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2903 "Unsupported extension header");
2904 gtp_extheader_req(gsn
, version
, &peer
, fd
, buffer
, status
);
2909 switch (pheader
->type
) {
2911 gtp_echo_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2914 gtp_echo_conf(gsn
, version
, &peer
, buffer
, status
);
2916 case GTP_SUPP_EXT_HEADER
:
2917 gtp_extheader_ind(gsn
, &peer
, buffer
, status
);
2920 gtp_error_ind_conf(gsn
, version
, &peer
, buffer
, status
);
2922 /* Supported header extensions */
2924 gtp_gpdu_ind(gsn
, version
, &peer
, fd
, buffer
, status
);
2928 gtp_errpack(LOG_ERR
, __FILE__
, __LINE__
, &peer
, buffer
, status
,
2929 "Unknown GTP message type received");
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
;
2943 memset(&addr
, 0, sizeof(addr
));
2944 addr
.sin_family
= AF_INET
;
2945 #if defined(__FreeBSD__) || defined(__APPLE__)
2946 addr
.sin_len
= sizeof(addr
);
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
);
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
)) {
2965 gtp_err(LOG_ERR
, __FILE__
, __LINE__
,
2966 "Memcpy failed: %d > %d", len
,
2967 sizeof (union gtp_packet
) - sizeof(struct gtp0_header
));
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
);
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
)) {
2986 gtp_err(LOG_ERR
, __FILE__
, __LINE__
,
2987 "Memcpy failed: %d > %d", len
,
2988 sizeof (union gtp_packet
) - sizeof(struct gtp0_header
));
2991 memcpy(packet
.gtp1l
.p
, pack
, len
); /* TODO Should be avoided! */
2994 gtp_err(LOG_ERR
, __FILE__
, __LINE__
,
2999 if (fcntl(fd
, F_SETFL
, 0)) {
3000 gtp_err(LOG_ERR
, __FILE__
, __LINE__
, "fnctl()");
3004 if (sendto(fd
, &packet
, length
, 0,
3005 (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
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
));
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]);
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
3037 *************************************************************/
3039 int ipv42eua(struct ul66_t
*eua
, struct in_addr
*src
) {
3040 eua
->v
[0] = 0xf1; /* IETF */
3041 eua
->v
[1] = 0x21; /* IPv4 */
3044 memcpy(&eua
->v
[2], src
, 4);
3053 int eua2ipv4(struct in_addr
*dst
, struct ul66_t
*eua
) {
3054 if ((eua
->l
!= 6) ||
3055 (eua
->v
[0] != 0xf1) ||
3057 return -1; /* Not IPv4 address*/
3058 memcpy(dst
, &eua
->v
[2], 4);
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
);
3069 int in_addr2gsna(struct ul16_t
*gsna
, struct in_addr
*src
) {
3070 memset(gsna
, 0, sizeof(struct ul16_t
));
3072 memcpy(gsna
->v
, src
, gsna
->l
);