blob: 8fd4a20aab027a19affe459a5644d03e6375dc1e [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
41int gtpie_tlv(void *p, int *length, int size, u_int8_t t, int l, void *v) {
42 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
50int gtpie_tv0(void *p, int *length, int size, u_int8_t t, int l, u_int8_t *v) {
51 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
58int gtpie_tv1(void *p, int *length, int size, u_int8_t t, u_int8_t v) {
59 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
66int gtpie_tv2(void *p, int *length, int size, u_int8_t t, u_int16_t v) {
67 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
74int gtpie_tv4(void *p, int *length, int size, u_int8_t t, u_int32_t v) {
75 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
82int gtpie_getie(union gtpie_member* ie[], int type, int instance) {
83 int j;
84 for (j=0; j< GTPIE_SIZE; j++) {
85 if ((ie[j] != 0) && (ie[j]->t == type)) {
86 if (instance-- == 0) return j;
87 }
88 }
89 return -1;
90}
91
92int gtpie_exist(union gtpie_member* ie[], int type, int instance) {
93 int j;
94 for (j=0; j< GTPIE_SIZE; j++) {
95 if ((ie[j] != 0) && (ie[j]->t == type)) {
96 if (instance-- == 0) return 1;
97 }
98 }
99 return 0;
100}
101
102int gtpie_gettlv(union gtpie_member* ie[], int type, int instance,
103 int *length, void *dst, int size){
104 int ien;
105 ien = gtpie_getie(ie, type, instance);
106 if (ien>=0) {
107 *length = ntoh16(ie[ien]->tlv.l);
108 if (*length <= size)
109 memcpy(dst, ie[ien]->tlv.v, *length);
110 else
111 return EOF;
112 }
113 return 0;
114}
115
116int gtpie_gettv0(union gtpie_member* ie[], int type, int instance,
117 void *dst, int size){
118 int ien;
119 ien = gtpie_getie(ie, type, instance);
120 if (ien>=0)
121 memcpy(dst, ie[ien]->tv0.v, size);
122 else
123 return EOF;
124 return 0;
125}
126
127int gtpie_gettv1(union gtpie_member* ie[], int type, int instance,
128 uint8_t *dst){
129 int ien;
130 ien = gtpie_getie(ie, type, instance);
131 if (ien>=0)
132 *dst = ntoh8(ie[ien]->tv1.v);
133 else
134 return EOF;
135 return 0;
136}
137
138int gtpie_gettv2(union gtpie_member* ie[], int type, int instance,
139 uint16_t *dst){
140 int ien;
141 ien = gtpie_getie(ie, type, instance);
142 if (ien>=0)
143 *dst = ntoh16(ie[ien]->tv2.v);
144 else
145 return EOF;
146 return 0;
147}
148
149int gtpie_gettv4(union gtpie_member* ie[], int type, int instance,
150 uint32_t *dst){
151 int ien;
152 ien = gtpie_getie(ie, type, instance);
153 if (ien>=0)
154 *dst = ntoh32(ie[ien]->tv4.v);
155 else
156 return EOF;
157 return 0;
158}
159
160int gtpie_decaps(union gtpie_member* ie[], void *pack, unsigned len) {
161 int i;
162 int j = 0;
163 unsigned char *p;
164 unsigned char *end;
165
166 end = (unsigned char*) pack + len;
167 p = pack;
168
169 memset(ie, 0, 4 * GTPIE_SIZE);
170
171 while (p<end) {
172 if (GTPIE_DEBUG) {
173 printf("The packet looks like this:\n");
174 for( i=0; i<(end-p); i++) {
175 printf("%02x ", (unsigned char)*(char *)(p+i));
176 if (!((i+1)%16)) printf("\n");
177 };
178 printf("\n");
179 }
180
181 switch (*p) {
182 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
183 case GTPIE_REORDER:
184 case GTPIE_MAP_CAUSE:
185 case GTPIE_MS_VALIDATED:
186 case GTPIE_RECOVERY:
187 case GTPIE_SELECTION_MODE:
188 case GTPIE_TEARDOWN:
189 case GTPIE_NSAPI:
190 case GTPIE_RANAP_CAUSE:
191 case GTPIE_RP_SMS:
192 case GTPIE_RP:
193 case GTPIE_MS_NOT_REACH:
194 if (j<GTPIE_SIZE) {
195 ie[j] = (union gtpie_member*) p;
196 if (GTPIE_DEBUG) printf("GTPIE TV1 found. Type %d, value %d\n",
197 ie[j]->tv1.t, ie[j]->tv1.v);
198 p+= 1 + 1;
199 j++;
200 }
201 break;
202 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
203 case GTPIE_FL_C:
204 case GTPIE_PFI:
205 case GTPIE_CHARGING_C:
206 case GTPIE_TRACE_REF:
207 case GTPIE_TRACE_TYPE:
208 if (j<GTPIE_SIZE) {
209 ie[j] = (union gtpie_member*) p;
210 if (GTPIE_DEBUG) printf("GTPIE TV2 found. Type %d, value %d\n",
211 ie[j]->tv2.t, ie[j]->tv2.v);
212 p+= 1 + 2;
213 j++;
214 }
215 break;
216 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
217 case GTPIE_P_TMSI_S:
218 if (j<GTPIE_SIZE) {
219 ie[j] = (union gtpie_member*) p;
220 if (GTPIE_DEBUG) printf("GTPIE TV 3 found. Type %d, value %d, %d, %d\n",
221 ie[j]->tv0.t, ie[j]->tv0.v[0],
222 ie[j]->tv0.v[1], ie[j]->tv0.v[2]);
223 p+= 1 + 3;
224 j++;
225 }
226 break;
227 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
228 case GTPIE_P_TMSI:
229 case GTPIE_CHARGING_ID:
230 if (j<GTPIE_SIZE) {
231 /* case GTPIE_TEI_DI: gtp1 */
232 /* case GTPIE_TEI_C: gtp1 */
233 ie[j] = (union gtpie_member*) p;
234 if (GTPIE_DEBUG) printf("GTPIE TV 4 found. Type %d, value %d\n",
235 ie[j]->tv4.t, ie[j]->tv4.v);
236 p+= 1 + 4;
237 j++;
238 }
239 break;
240 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
241 if (j<GTPIE_SIZE) {
242 ie[j] = (union gtpie_member*) p;
243 if (GTPIE_DEBUG) printf("GTPIE TV 5 found. Type %d\n", ie[j]->tv0.t);
244 p+= 1 + 5;
245 j++;
246 }
247 break;
248 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
249 if (j<GTPIE_SIZE) {
250 ie[j] = (union gtpie_member*) p;
251 if (GTPIE_DEBUG) printf("GTPIE TV 7 found. Type %d\n", ie[j]->tv0.t);
252 p+= 1 + 7;
253 j++;
254 }
255 break;
256 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
257 case GTPIE_RAI:
258 if (j<GTPIE_SIZE) {
259 ie[j] = (union gtpie_member*) p;
260 if (GTPIE_DEBUG) printf("GTPIE TV 8 found. Type %d, value 0x%llx\n",
261 ie[j]->tv0.t, ie[j]->tv8.v);
262 p+= 1 + 8;
263 j++;
264 }
265 break;
266 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
267 if (j<GTPIE_SIZE) {
268 ie[j] = (union gtpie_member*) p;
269 if (GTPIE_DEBUG) printf("GTPIE TV 28 found. Type %d\n", ie[j]->tv0.t);
270 p+= 1 + 28;
271 j++;
272 }
273 break;
274 case GTPIE_EXT_HEADER_T: /* GTP extension header */
275 if (j<GTPIE_SIZE) {
276 ie[j] = (union gtpie_member*) p;
277 if (GTPIE_DEBUG) printf("GTPIE GTP extension header found. Type %d\n",
278 ie[j]->ext.t);
279 p+= 2 + ntoh8(ie[j]->ext.l);
280 j++;
281 }
282 break;
283 case GTPIE_EUA: /* TLV GTPIE types with variable length */
284 case GTPIE_MM_CONTEXT:
285 case GTPIE_PDP_CONTEXT:
286 case GTPIE_APN:
287 case GTPIE_PCO:
288 case GTPIE_GSN_ADDR:
289 case GTPIE_MSISDN:
290 case GTPIE_QOS_PROFILE:
291 case GTPIE_AUTH_QUINTUP:
292 case GTPIE_TFT:
293 case GTPIE_TARGET_INF:
294 case GTPIE_UTRAN_TRANS:
295 case GTPIE_RAB_SETUP:
296 case GTPIE_TRIGGER_ID:
297 case GTPIE_OMC_ID:
298 case GTPIE_CHARGING_ADDR:
299 case GTPIE_PRIVATE:
300 if (j<GTPIE_SIZE) {
301 ie[j] = (union gtpie_member*) p;
302 if (GTPIE_DEBUG) printf("GTPIE TLV found. Type %d\n", ie[j]->tlv.t);
303 p+= 3 + ntoh16(ie[j]->tlv.l);
304 j++;
305 }
306 break;
307 default:
308 if (GTPIE_DEBUG) printf("GTPIE something unknown. Type %d\n", *p);
309 return EOF; /* We received something unknown */
310 }
311 }
312 if (p==end) {
313 if (GTPIE_DEBUG) printf("GTPIE normal return. %lx %lx\n",
314 (unsigned long) p, (unsigned long) end);
315 return 0; /* We landed at the end of the packet: OK */
316 }
317 else {
318 if (GTPIE_DEBUG) printf("GTPIE exceeded end of packet. %lx %lx\n",
319 (unsigned long) p, (unsigned long) end);
320 return EOF; /* We exceeded the end of the packet: Error */
321 }
322}
323
324int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len) {
325 int i;
326 unsigned char *p;
327 unsigned char *end;
328 union gtpie_member *m;
329 int iesize;
330
331 p = pack;
332
333 memset(pack, 0, GTPIE_MAX);
334 end = p + GTPIE_MAX;
335 for (i=1; i<GTPIE_SIZE; i++) if (ie[i] != 0) {
336 if (GTPIE_DEBUG) printf("gtpie_encaps. Type %d\n", i);
337 m=(union gtpie_member *)p;
338 switch (i) {
339 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
340 case GTPIE_REORDER:
341 case GTPIE_MAP_CAUSE:
342 case GTPIE_MS_VALIDATED:
343 case GTPIE_RECOVERY:
344 case GTPIE_SELECTION_MODE:
345 case GTPIE_TEARDOWN:
346 case GTPIE_NSAPI:
347 case GTPIE_RANAP_CAUSE:
348 case GTPIE_RP_SMS:
349 case GTPIE_RP:
350 case GTPIE_MS_NOT_REACH:
351 iesize = 2;
352 break;
353 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
354 case GTPIE_FL_C:
355 case GTPIE_PFI:
356 case GTPIE_CHARGING_C:
357 case GTPIE_TRACE_REF:
358 case GTPIE_TRACE_TYPE:
359 iesize = 3;
360 break;
361 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
362 case GTPIE_P_TMSI_S:
363 iesize = 4;
364 break;
365 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
366 case GTPIE_P_TMSI:
367 /* case GTPIE_TEI_DI: only in gtp1*/
368 /* case GTPIE_TEI_C: only in gtp1*/
369 case GTPIE_CHARGING_ID:
370 iesize = 5;
371 break;
372 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
373 iesize = 6;
374 break;
375 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
376 iesize = 8;
377 break;
378 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
379 case GTPIE_RAI:
380 iesize = 9;
381 break;
382 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
383 iesize = 29;
384 break;
385 case GTPIE_EXT_HEADER_T: /* GTP extension header */
386 iesize = 2 + hton8(ie[i]->ext.l);
387 break;
388 case GTPIE_EUA: /* TLV GTPIE types with length length 2 */
389 case GTPIE_MM_CONTEXT:
390 case GTPIE_PDP_CONTEXT:
391 case GTPIE_APN:
392 case GTPIE_PCO:
393 case GTPIE_GSN_ADDR:
394 case GTPIE_MSISDN:
395 case GTPIE_QOS_PROFILE:
396 case GTPIE_AUTH_QUINTUP:
397 case GTPIE_TFT:
398 case GTPIE_TARGET_INF:
399 case GTPIE_UTRAN_TRANS:
400 case GTPIE_RAB_SETUP:
401 case GTPIE_TRIGGER_ID:
402 case GTPIE_OMC_ID:
403 case GTPIE_CHARGING_ADDR:
404 case GTPIE_PRIVATE:
405 iesize = 3 + hton16(ie[i]->tlv.l);
406 break;
407 default:
408 return 2; /* We received something unknown */
409 }
410 if (p+iesize < end) {
411 memcpy(p, ie[i], iesize);
412 p += iesize;
413 *len += iesize;
414 }
415 else return 2; /* Out of space */
416 }
417 return 0;
418}
419
420int gtpie_encaps2(union gtpie_member ie[], int size,
421 void *pack, unsigned *len) {
422 int i, j;
423 unsigned char *p;
424 unsigned char *end;
425 union gtpie_member *m;
426 int iesize;
427
428 p = pack;
429
430 memset(pack, 0, GTPIE_MAX);
431 end = p + GTPIE_MAX;
432 for (j=0; j<GTPIE_SIZE; j++) for (i=0; i<size; i++) if (ie[i].t == j) {
433 if (GTPIE_DEBUG) printf("gtpie_encaps. Number %d, Type %d\n", i, ie[i].t);
434 m=(union gtpie_member *)p;
435 switch (ie[i].t) {
436 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
437 case GTPIE_REORDER:
438 case GTPIE_MAP_CAUSE:
439 case GTPIE_MS_VALIDATED:
440 case GTPIE_RECOVERY:
441 case GTPIE_SELECTION_MODE:
442 case GTPIE_TEARDOWN:
443 case GTPIE_NSAPI:
444 case GTPIE_RANAP_CAUSE:
445 case GTPIE_RP_SMS:
446 case GTPIE_RP:
447 case GTPIE_MS_NOT_REACH:
448 iesize = 2;
449 break;
450 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
451 case GTPIE_CHARGING_C:
452 case GTPIE_TRACE_REF:
453 case GTPIE_TRACE_TYPE:
454 iesize = 3;
455 break;
456 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
457 case GTPIE_P_TMSI_S:
458 iesize = 4;
459 break;
460 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
461 case GTPIE_P_TMSI:
462 case GTPIE_TEI_DI:
463 case GTPIE_TEI_C:
464 iesize = 5;
465 break;
466 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
467 iesize = 6;
468 break;
469 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
470 iesize = 8;
471 break;
472 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
473 case GTPIE_RAI:
474 iesize = 9;
475 break;
476 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
477 iesize = 29;
478 break;
479 case GTPIE_EXT_HEADER_T: /* GTP extension header */
480 iesize = 2 + hton8(ie[i].ext.l);
481 break;
482 case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */
483 case GTPIE_EUA:
484 case GTPIE_MM_CONTEXT:
485 case GTPIE_PDP_CONTEXT:
486 case GTPIE_APN:
487 case GTPIE_PCO:
488 case GTPIE_GSN_ADDR:
489 case GTPIE_MSISDN:
490 case GTPIE_QOS_PROFILE:
491 case GTPIE_AUTH_QUINTUP:
492 case GTPIE_TFT:
493 case GTPIE_TARGET_INF:
494 case GTPIE_UTRAN_TRANS:
495 case GTPIE_RAB_SETUP:
496 case GTPIE_TRIGGER_ID:
497 case GTPIE_OMC_ID:
498 case GTPIE_CHARGING_ADDR:
499 case GTPIE_PRIVATE:
500 iesize = 3 + hton16(ie[i].tlv.l);
501 break;
502 default:
503 return 2; /* We received something unknown */
504 }
505 if (p+iesize < end) {
506 memcpy(p, &ie[i], iesize);
507 p += iesize;
508 *len += iesize;
509 }
510 else return 2; /* Out of space */
511 }
512 return 0;
513}