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