blob: a62d02c448a18600c9c229a20dffde1da3bf059c [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002 Mondru AB.
4 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
jjako52c24142002-12-16 13:33:51 +000010 */
11
12/*
13 * gtpie.c: Contains functions to encapsulate and decapsulate GTP
14 * information elements
15 *
16 *
17 * Encapsulation
18 * - gtpie_tlv, gtpie_tv0, gtpie_tv1, gtpie_tv2 ... Adds information
19 * elements to a buffer.
20 *
21 * Decapsulation
22 * - gtpie_decaps: Returns array with pointers to information elements.
23 * - getie_getie: Returns the pointer of a particular element.
24 * - gtpie_gettlv: Copies tlv information element. Return 0 on success.
25 * - gtpie_gettv: Copies tv information element. Return 0 on success.
26 *
27 */
28
jjako0fe0df02004-09-17 11:30:40 +000029#include <../config.h>
30
31#ifdef HAVE_STDINT_H
32#include <stdint.h>
33#endif
34
jjako52c24142002-12-16 13:33:51 +000035#include <stdio.h>
36#include <sys/types.h>
37#include <netinet/in.h>
38#include <string.h>
39
40#include "gtpie.h"
41
jjakob7b93fc2004-01-09 11:56:48 +000042int gtpie_tlv(void *p, int *length, int size, uint8_t t, int l, void *v) {
jjako52c24142002-12-16 13:33:51 +000043 if ((*length + 3 + l) >= size) return 1;
44 ((union gtpie_member*) (p + *length))->tlv.t = hton8(t);
45 ((union gtpie_member*) (p + *length))->tlv.l = hton16(l);
46 memcpy((void*) (p + *length +3), v, l);
47 *length += 3 + l;
48 return 0;
49}
50
jjakob7b93fc2004-01-09 11:56:48 +000051int gtpie_tv0(void *p, int *length, int size, uint8_t t, int l, uint8_t *v) {
jjako52c24142002-12-16 13:33:51 +000052 if ((*length + 1 + l) >= size) return 1;
53 ((union gtpie_member*) (p + *length))->tv0.t = hton8(t);
54 memcpy((void*) (p + *length +1), v, l);
55 *length += 1 + l;
56 return 0;
57}
58
jjakob7b93fc2004-01-09 11:56:48 +000059int gtpie_tv1(void *p, int *length, int size, uint8_t t, uint8_t v) {
jjako52c24142002-12-16 13:33:51 +000060 if ((*length + 2) >= size) return 1;
61 ((union gtpie_member*) (p + *length))->tv1.t = hton8(t);
62 ((union gtpie_member*) (p + *length))->tv1.v = hton8(v);
63 *length += 2;
64 return 0;
65}
66
jjakob7b93fc2004-01-09 11:56:48 +000067int gtpie_tv2(void *p, int *length, int size, uint8_t t, uint16_t v) {
jjako52c24142002-12-16 13:33:51 +000068 if ((*length + 3) >= size) return 1;
69 ((union gtpie_member*) (p + *length))->tv2.t = hton8(t);
70 ((union gtpie_member*) (p + *length))->tv2.v = hton16(v);
71 *length += 3;
72 return 0;
73}
74
jjakob7b93fc2004-01-09 11:56:48 +000075int gtpie_tv4(void *p, int *length, int size, uint8_t t, uint32_t v) {
jjako52c24142002-12-16 13:33:51 +000076 if ((*length + 5) >= size) return 1;
77 ((union gtpie_member*) (p + *length))->tv4.t = hton8(t);
78 ((union gtpie_member*) (p + *length))->tv4.v = hton32(v);
79 *length += 5;
80 return 0;
81}
82
jjakob7b93fc2004-01-09 11:56:48 +000083int gtpie_tv8(void *p, int *length, int size, uint8_t t, uint64_t v) {
jjako08d331d2003-10-13 20:33:30 +000084 if ((*length + 9) >= size) return 1;
85 ((union gtpie_member*) (p + *length))->tv8.t = hton8(t);
86 ((union gtpie_member*) (p + *length))->tv8.v = hton64(v);
87 *length += 9;
88 return 0;
89}
90
jjako52c24142002-12-16 13:33:51 +000091int gtpie_getie(union gtpie_member* ie[], int type, int instance) {
92 int j;
93 for (j=0; j< GTPIE_SIZE; j++) {
94 if ((ie[j] != 0) && (ie[j]->t == type)) {
95 if (instance-- == 0) return j;
96 }
97 }
98 return -1;
99}
100
101int gtpie_exist(union gtpie_member* ie[], int type, int instance) {
102 int j;
103 for (j=0; j< GTPIE_SIZE; j++) {
104 if ((ie[j] != 0) && (ie[j]->t == type)) {
105 if (instance-- == 0) return 1;
106 }
107 }
108 return 0;
109}
110
111int gtpie_gettlv(union gtpie_member* ie[], int type, int instance,
112 int *length, void *dst, int size){
113 int ien;
114 ien = gtpie_getie(ie, type, instance);
115 if (ien>=0) {
116 *length = ntoh16(ie[ien]->tlv.l);
117 if (*length <= size)
118 memcpy(dst, ie[ien]->tlv.v, *length);
119 else
120 return EOF;
121 }
122 return 0;
123}
124
125int gtpie_gettv0(union gtpie_member* ie[], int type, int instance,
126 void *dst, int size){
127 int ien;
128 ien = gtpie_getie(ie, type, instance);
129 if (ien>=0)
130 memcpy(dst, ie[ien]->tv0.v, size);
131 else
132 return EOF;
133 return 0;
134}
135
136int gtpie_gettv1(union gtpie_member* ie[], int type, int instance,
137 uint8_t *dst){
138 int ien;
139 ien = gtpie_getie(ie, type, instance);
140 if (ien>=0)
141 *dst = ntoh8(ie[ien]->tv1.v);
142 else
143 return EOF;
144 return 0;
145}
146
147int gtpie_gettv2(union gtpie_member* ie[], int type, int instance,
148 uint16_t *dst){
149 int ien;
150 ien = gtpie_getie(ie, type, instance);
151 if (ien>=0)
152 *dst = ntoh16(ie[ien]->tv2.v);
153 else
154 return EOF;
155 return 0;
156}
157
158int gtpie_gettv4(union gtpie_member* ie[], int type, int instance,
159 uint32_t *dst){
160 int ien;
161 ien = gtpie_getie(ie, type, instance);
162 if (ien>=0)
163 *dst = ntoh32(ie[ien]->tv4.v);
164 else
165 return EOF;
166 return 0;
167}
168
jjako08d331d2003-10-13 20:33:30 +0000169int gtpie_gettv8(union gtpie_member* ie[], int type, int instance,
170 uint64_t *dst){
171 int ien;
172 ien = gtpie_getie(ie, type, instance);
173 if (ien>=0)
174 *dst = ntoh64(ie[ien]->tv8.v);
175 else
176 return EOF;
177 return 0;
178}
179
180int gtpie_decaps(union gtpie_member* ie[], int version, void *pack, unsigned len) {
jjako52c24142002-12-16 13:33:51 +0000181 int i;
182 int j = 0;
183 unsigned char *p;
184 unsigned char *end;
185
186 end = (unsigned char*) pack + len;
187 p = pack;
188
189 memset(ie, 0, 4 * GTPIE_SIZE);
190
Harald Weltee67556e2010-05-04 10:59:23 +0200191 while ((p<end) && (j<GTPIE_SIZE)) {
jjako52c24142002-12-16 13:33:51 +0000192 if (GTPIE_DEBUG) {
193 printf("The packet looks like this:\n");
194 for( i=0; i<(end-p); i++) {
195 printf("%02x ", (unsigned char)*(char *)(p+i));
196 if (!((i+1)%16)) printf("\n");
197 };
jjako08d331d2003-10-13 20:33:30 +0000198 printf("\n");
jjako52c24142002-12-16 13:33:51 +0000199 }
jjako08d331d2003-10-13 20:33:30 +0000200
jjako52c24142002-12-16 13:33:51 +0000201 switch (*p) {
202 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
203 case GTPIE_REORDER:
204 case GTPIE_MAP_CAUSE:
205 case GTPIE_MS_VALIDATED:
206 case GTPIE_RECOVERY:
207 case GTPIE_SELECTION_MODE:
208 case GTPIE_TEARDOWN:
209 case GTPIE_NSAPI:
210 case GTPIE_RANAP_CAUSE:
211 case GTPIE_RP_SMS:
212 case GTPIE_RP:
213 case GTPIE_MS_NOT_REACH:
214 if (j<GTPIE_SIZE) {
215 ie[j] = (union gtpie_member*) p;
216 if (GTPIE_DEBUG) printf("GTPIE TV1 found. Type %d, value %d\n",
jjako08d331d2003-10-13 20:33:30 +0000217 ie[j]->tv1.t, ie[j]->tv1.v);
jjako52c24142002-12-16 13:33:51 +0000218 p+= 1 + 1;
219 j++;
220 }
221 break;
jjako08d331d2003-10-13 20:33:30 +0000222 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 or 4 */
jjako52c24142002-12-16 13:33:51 +0000223 case GTPIE_FL_C:
jjako08d331d2003-10-13 20:33:30 +0000224 if (version != 0) {
225 if (j<GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
226 /* case GTPIE_TEI_DI: gtp1 */
227 /* case GTPIE_TEI_C: gtp1 */
228 ie[j] = (union gtpie_member*) p;
229 if (GTPIE_DEBUG) printf("GTPIE TV 4 found. Type %d, value %d\n",
230 ie[j]->tv4.t, ie[j]->tv4.v);
231 p+= 1 + 4;
232 j++;
233 }
234 break;
235 }
236 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
jjako52c24142002-12-16 13:33:51 +0000237 case GTPIE_CHARGING_C:
238 case GTPIE_TRACE_REF:
239 case GTPIE_TRACE_TYPE:
240 if (j<GTPIE_SIZE) {
241 ie[j] = (union gtpie_member*) p;
242 if (GTPIE_DEBUG) printf("GTPIE TV2 found. Type %d, value %d\n",
243 ie[j]->tv2.t, ie[j]->tv2.v);
244 p+= 1 + 2;
245 j++;
246 }
247 break;
248 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
249 case GTPIE_P_TMSI_S:
250 if (j<GTPIE_SIZE) {
251 ie[j] = (union gtpie_member*) p;
252 if (GTPIE_DEBUG) printf("GTPIE TV 3 found. Type %d, value %d, %d, %d\n",
253 ie[j]->tv0.t, ie[j]->tv0.v[0],
254 ie[j]->tv0.v[1], ie[j]->tv0.v[2]);
255 p+= 1 + 3;
256 j++;
257 }
258 break;
259 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
260 case GTPIE_P_TMSI:
261 case GTPIE_CHARGING_ID:
jjako08d331d2003-10-13 20:33:30 +0000262 /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
263 /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
jjako52c24142002-12-16 13:33:51 +0000264 if (j<GTPIE_SIZE) {
jjako52c24142002-12-16 13:33:51 +0000265 ie[j] = (union gtpie_member*) p;
266 if (GTPIE_DEBUG) printf("GTPIE TV 4 found. Type %d, value %d\n",
267 ie[j]->tv4.t, ie[j]->tv4.v);
268 p+= 1 + 4;
269 j++;
270 }
271 break;
272 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
273 if (j<GTPIE_SIZE) {
274 ie[j] = (union gtpie_member*) p;
275 if (GTPIE_DEBUG) printf("GTPIE TV 5 found. Type %d\n", ie[j]->tv0.t);
276 p+= 1 + 5;
277 j++;
278 }
279 break;
280 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
281 if (j<GTPIE_SIZE) {
282 ie[j] = (union gtpie_member*) p;
283 if (GTPIE_DEBUG) printf("GTPIE TV 7 found. Type %d\n", ie[j]->tv0.t);
284 p+= 1 + 7;
285 j++;
286 }
287 break;
288 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
289 case GTPIE_RAI:
290 if (j<GTPIE_SIZE) {
291 ie[j] = (union gtpie_member*) p;
292 if (GTPIE_DEBUG) printf("GTPIE TV 8 found. Type %d, value 0x%llx\n",
293 ie[j]->tv0.t, ie[j]->tv8.v);
294 p+= 1 + 8;
295 j++;
296 }
297 break;
298 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
299 if (j<GTPIE_SIZE) {
300 ie[j] = (union gtpie_member*) p;
301 if (GTPIE_DEBUG) printf("GTPIE TV 28 found. Type %d\n", ie[j]->tv0.t);
302 p+= 1 + 28;
303 j++;
304 }
305 break;
306 case GTPIE_EXT_HEADER_T: /* GTP extension header */
307 if (j<GTPIE_SIZE) {
308 ie[j] = (union gtpie_member*) p;
309 if (GTPIE_DEBUG) printf("GTPIE GTP extension header found. Type %d\n",
310 ie[j]->ext.t);
311 p+= 2 + ntoh8(ie[j]->ext.l);
312 j++;
313 }
314 break;
315 case GTPIE_EUA: /* TLV GTPIE types with variable length */
316 case GTPIE_MM_CONTEXT:
317 case GTPIE_PDP_CONTEXT:
318 case GTPIE_APN:
319 case GTPIE_PCO:
320 case GTPIE_GSN_ADDR:
321 case GTPIE_MSISDN:
322 case GTPIE_QOS_PROFILE:
323 case GTPIE_AUTH_QUINTUP:
324 case GTPIE_TFT:
325 case GTPIE_TARGET_INF:
326 case GTPIE_UTRAN_TRANS:
327 case GTPIE_RAB_SETUP:
328 case GTPIE_TRIGGER_ID:
329 case GTPIE_OMC_ID:
330 case GTPIE_CHARGING_ADDR:
331 case GTPIE_PRIVATE:
332 if (j<GTPIE_SIZE) {
333 ie[j] = (union gtpie_member*) p;
334 if (GTPIE_DEBUG) printf("GTPIE TLV found. Type %d\n", ie[j]->tlv.t);
335 p+= 3 + ntoh16(ie[j]->tlv.l);
336 j++;
337 }
338 break;
339 default:
340 if (GTPIE_DEBUG) printf("GTPIE something unknown. Type %d\n", *p);
341 return EOF; /* We received something unknown */
342 }
343 }
344 if (p==end) {
345 if (GTPIE_DEBUG) printf("GTPIE normal return. %lx %lx\n",
346 (unsigned long) p, (unsigned long) end);
347 return 0; /* We landed at the end of the packet: OK */
348 }
Harald Weltee67556e2010-05-04 10:59:23 +0200349 else if (!(j<GTPIE_SIZE)) {
350 if (GTPIE_DEBUG) printf("GTPIE too many elements.\n");
351 return EOF; /* We received too many information elements */
352 }
jjako52c24142002-12-16 13:33:51 +0000353 else {
354 if (GTPIE_DEBUG) printf("GTPIE exceeded end of packet. %lx %lx\n",
355 (unsigned long) p, (unsigned long) end);
356 return EOF; /* We exceeded the end of the packet: Error */
357 }
358}
359
360int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len) {
361 int i;
362 unsigned char *p;
363 unsigned char *end;
364 union gtpie_member *m;
365 int iesize;
366
367 p = pack;
368
369 memset(pack, 0, GTPIE_MAX);
370 end = p + GTPIE_MAX;
371 for (i=1; i<GTPIE_SIZE; i++) if (ie[i] != 0) {
372 if (GTPIE_DEBUG) printf("gtpie_encaps. Type %d\n", i);
373 m=(union gtpie_member *)p;
374 switch (i) {
375 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
376 case GTPIE_REORDER:
377 case GTPIE_MAP_CAUSE:
378 case GTPIE_MS_VALIDATED:
379 case GTPIE_RECOVERY:
380 case GTPIE_SELECTION_MODE:
381 case GTPIE_TEARDOWN:
382 case GTPIE_NSAPI:
383 case GTPIE_RANAP_CAUSE:
384 case GTPIE_RP_SMS:
385 case GTPIE_RP:
386 case GTPIE_MS_NOT_REACH:
387 iesize = 2;
388 break;
389 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
390 case GTPIE_FL_C:
391 case GTPIE_PFI:
392 case GTPIE_CHARGING_C:
393 case GTPIE_TRACE_REF:
394 case GTPIE_TRACE_TYPE:
395 iesize = 3;
396 break;
397 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
398 case GTPIE_P_TMSI_S:
399 iesize = 4;
400 break;
401 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
402 case GTPIE_P_TMSI:
403 /* case GTPIE_TEI_DI: only in gtp1*/
404 /* case GTPIE_TEI_C: only in gtp1*/
405 case GTPIE_CHARGING_ID:
406 iesize = 5;
407 break;
408 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
409 iesize = 6;
410 break;
411 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
412 iesize = 8;
413 break;
414 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
415 case GTPIE_RAI:
416 iesize = 9;
417 break;
418 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
419 iesize = 29;
420 break;
421 case GTPIE_EXT_HEADER_T: /* GTP extension header */
422 iesize = 2 + hton8(ie[i]->ext.l);
423 break;
424 case GTPIE_EUA: /* TLV GTPIE types with length length 2 */
425 case GTPIE_MM_CONTEXT:
426 case GTPIE_PDP_CONTEXT:
427 case GTPIE_APN:
428 case GTPIE_PCO:
429 case GTPIE_GSN_ADDR:
430 case GTPIE_MSISDN:
431 case GTPIE_QOS_PROFILE:
432 case GTPIE_AUTH_QUINTUP:
433 case GTPIE_TFT:
434 case GTPIE_TARGET_INF:
435 case GTPIE_UTRAN_TRANS:
436 case GTPIE_RAB_SETUP:
437 case GTPIE_TRIGGER_ID:
438 case GTPIE_OMC_ID:
439 case GTPIE_CHARGING_ADDR:
440 case GTPIE_PRIVATE:
441 iesize = 3 + hton16(ie[i]->tlv.l);
442 break;
443 default:
444 return 2; /* We received something unknown */
445 }
446 if (p+iesize < end) {
447 memcpy(p, ie[i], iesize);
448 p += iesize;
449 *len += iesize;
450 }
451 else return 2; /* Out of space */
452 }
453 return 0;
454}
455
456int gtpie_encaps2(union gtpie_member ie[], int size,
457 void *pack, unsigned *len) {
458 int i, j;
459 unsigned char *p;
460 unsigned char *end;
461 union gtpie_member *m;
462 int iesize;
463
464 p = pack;
465
466 memset(pack, 0, GTPIE_MAX);
467 end = p + GTPIE_MAX;
468 for (j=0; j<GTPIE_SIZE; j++) for (i=0; i<size; i++) if (ie[i].t == j) {
469 if (GTPIE_DEBUG) printf("gtpie_encaps. Number %d, Type %d\n", i, ie[i].t);
470 m=(union gtpie_member *)p;
471 switch (ie[i].t) {
472 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
473 case GTPIE_REORDER:
474 case GTPIE_MAP_CAUSE:
475 case GTPIE_MS_VALIDATED:
476 case GTPIE_RECOVERY:
477 case GTPIE_SELECTION_MODE:
478 case GTPIE_TEARDOWN:
479 case GTPIE_NSAPI:
480 case GTPIE_RANAP_CAUSE:
481 case GTPIE_RP_SMS:
482 case GTPIE_RP:
483 case GTPIE_MS_NOT_REACH:
484 iesize = 2;
485 break;
486 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
487 case GTPIE_CHARGING_C:
488 case GTPIE_TRACE_REF:
489 case GTPIE_TRACE_TYPE:
490 iesize = 3;
491 break;
492 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
493 case GTPIE_P_TMSI_S:
494 iesize = 4;
495 break;
496 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
497 case GTPIE_P_TMSI:
498 case GTPIE_TEI_DI:
499 case GTPIE_TEI_C:
500 iesize = 5;
501 break;
502 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
503 iesize = 6;
504 break;
505 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
506 iesize = 8;
507 break;
508 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
509 case GTPIE_RAI:
510 iesize = 9;
511 break;
512 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
513 iesize = 29;
514 break;
515 case GTPIE_EXT_HEADER_T: /* GTP extension header */
516 iesize = 2 + hton8(ie[i].ext.l);
517 break;
518 case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */
519 case GTPIE_EUA:
520 case GTPIE_MM_CONTEXT:
521 case GTPIE_PDP_CONTEXT:
522 case GTPIE_APN:
523 case GTPIE_PCO:
524 case GTPIE_GSN_ADDR:
525 case GTPIE_MSISDN:
526 case GTPIE_QOS_PROFILE:
527 case GTPIE_AUTH_QUINTUP:
528 case GTPIE_TFT:
529 case GTPIE_TARGET_INF:
530 case GTPIE_UTRAN_TRANS:
531 case GTPIE_RAB_SETUP:
532 case GTPIE_TRIGGER_ID:
533 case GTPIE_OMC_ID:
534 case GTPIE_CHARGING_ADDR:
535 case GTPIE_PRIVATE:
536 iesize = 3 + hton16(ie[i].tlv.l);
537 break;
538 default:
539 return 2; /* We received something unknown */
540 }
541 if (p+iesize < end) {
542 memcpy(p, &ie[i], iesize);
543 p += iesize;
544 *len += iesize;
545 }
546 else return 2; /* Out of space */
547 }
548 return 0;
549}