blob: c8db449125a6fdd32f5e9c6e406eeb438e130311 [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
Harald Weltebed35df2011-11-02 13:06:18 +010042int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_t t,
43 int l, void *v)
44{
45 if ((*length + 3 + l) >= size)
46 return 1;
47 ((union gtpie_member *)(p + *length))->tlv.t = hton8(t);
48 ((union gtpie_member *)(p + *length))->tlv.l = hton16(l);
49 memcpy((void *)(p + *length + 3), v, l);
50 *length += 3 + l;
51 return 0;
jjako52c24142002-12-16 13:33:51 +000052}
53
Harald Weltebed35df2011-11-02 13:06:18 +010054int gtpie_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t,
55 int l, uint8_t * v)
56{
57 if ((*length + 1 + l) >= size)
58 return 1;
59 ((union gtpie_member *)(p + *length))->tv0.t = hton8(t);
60 memcpy((void *)(p + *length + 1), v, l);
61 *length += 1 + l;
62 return 0;
jjako52c24142002-12-16 13:33:51 +000063}
64
Harald Weltebed35df2011-11-02 13:06:18 +010065int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t,
66 uint8_t v)
67{
68 if ((*length + 2) >= size)
69 return 1;
70 ((union gtpie_member *)(p + *length))->tv1.t = hton8(t);
71 ((union gtpie_member *)(p + *length))->tv1.v = hton8(v);
72 *length += 2;
73 return 0;
jjako52c24142002-12-16 13:33:51 +000074}
75
Harald Weltebed35df2011-11-02 13:06:18 +010076int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t,
77 uint16_t v)
78{
79 if ((*length + 3) >= size)
80 return 1;
81 ((union gtpie_member *)(p + *length))->tv2.t = hton8(t);
82 ((union gtpie_member *)(p + *length))->tv2.v = hton16(v);
83 *length += 3;
84 return 0;
jjako52c24142002-12-16 13:33:51 +000085}
86
Harald Weltebed35df2011-11-02 13:06:18 +010087int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t,
88 uint32_t v)
89{
90 if ((*length + 5) >= size)
91 return 1;
92 ((union gtpie_member *)(p + *length))->tv4.t = hton8(t);
93 ((union gtpie_member *)(p + *length))->tv4.v = hton32(v);
94 *length += 5;
95 return 0;
jjako52c24142002-12-16 13:33:51 +000096}
97
Harald Weltebed35df2011-11-02 13:06:18 +010098int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t,
99 uint64_t v)
100{
101 if ((*length + 9) >= size)
102 return 1;
103 ((union gtpie_member *)(p + *length))->tv8.t = hton8(t);
104 ((union gtpie_member *)(p + *length))->tv8.v = hton64(v);
105 *length += 9;
106 return 0;
jjako08d331d2003-10-13 20:33:30 +0000107}
108
Harald Weltebed35df2011-11-02 13:06:18 +0100109int gtpie_getie(union gtpie_member *ie[], int type, int instance)
110{
111 int j;
112 for (j = 0; j < GTPIE_SIZE; j++) {
113 if ((ie[j] != 0) && (ie[j]->t == type)) {
114 if (instance-- == 0)
115 return j;
116 }
jjako08d331d2003-10-13 20:33:30 +0000117 }
Harald Weltebed35df2011-11-02 13:06:18 +0100118 return -1;
jjako52c24142002-12-16 13:33:51 +0000119}
120
Harald Weltebed35df2011-11-02 13:06:18 +0100121int gtpie_exist(union gtpie_member *ie[], int type, int instance)
122{
123 int j;
124 for (j = 0; j < GTPIE_SIZE; j++) {
125 if ((ie[j] != 0) && (ie[j]->t == type)) {
126 if (instance-- == 0)
127 return 1;
128 }
129 }
130 return 0;
131}
jjako52c24142002-12-16 13:33:51 +0000132
Harald Weltebed35df2011-11-02 13:06:18 +0100133int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
134 unsigned int *length, void *dst, unsigned int size)
135{
136 int ien;
137 ien = gtpie_getie(ie, type, instance);
138 if (ien >= 0) {
139 *length = ntoh16(ie[ien]->tlv.l);
140 if (*length <= size)
141 memcpy(dst, ie[ien]->tlv.v, *length);
142 else
143 return EOF;
144 }
145 return 0;
146}
147
148int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
149 void *dst, unsigned int size)
150{
151 int ien;
152 ien = gtpie_getie(ie, type, instance);
153 if (ien >= 0)
154 memcpy(dst, ie[ien]->tv0.v, size);
155 else
156 return EOF;
157 return 0;
158}
159
160int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
161 uint8_t * dst)
162{
163 int ien;
164 ien = gtpie_getie(ie, type, instance);
165 if (ien >= 0)
166 *dst = ntoh8(ie[ien]->tv1.v);
167 else
168 return EOF;
169 return 0;
170}
171
172int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
173 uint16_t * dst)
174{
175 int ien;
176 ien = gtpie_getie(ie, type, instance);
177 if (ien >= 0)
178 *dst = ntoh16(ie[ien]->tv2.v);
179 else
180 return EOF;
181 return 0;
182}
183
184int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
185 uint32_t * dst)
186{
187 int ien;
188 ien = gtpie_getie(ie, type, instance);
189 if (ien >= 0)
190 *dst = ntoh32(ie[ien]->tv4.v);
191 else
192 return EOF;
193 return 0;
194}
195
196int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
197 uint64_t * dst)
198{
199 int ien;
200 ien = gtpie_getie(ie, type, instance);
201 if (ien >= 0)
202 *dst = ntoh64(ie[ien]->tv8.v);
203 else
204 return EOF;
205 return 0;
206}
207
208int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
209 unsigned len)
210{
211 int i;
212 int j = 0;
213 unsigned char *p;
214 unsigned char *end;
215
216 end = (unsigned char *)pack + len;
217 p = pack;
218
219 memset(ie, 0, sizeof(union gtpie_member *) * GTPIE_SIZE);
220
221 while ((p < end) && (j < GTPIE_SIZE)) {
222 if (GTPIE_DEBUG) {
223 printf("The packet looks like this:\n");
224 for (i = 0; i < (end - p); i++) {
225 printf("%02x ",
226 (unsigned char)*(char *)(p + i));
227 if (!((i + 1) % 16))
228 printf("\n");
229 };
230 printf("\n");
231 }
232
233 switch (*p) {
234 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
235 case GTPIE_REORDER:
236 case GTPIE_MAP_CAUSE:
237 case GTPIE_MS_VALIDATED:
238 case GTPIE_RECOVERY:
239 case GTPIE_SELECTION_MODE:
240 case GTPIE_TEARDOWN:
241 case GTPIE_NSAPI:
242 case GTPIE_RANAP_CAUSE:
243 case GTPIE_RP_SMS:
244 case GTPIE_RP:
245 case GTPIE_MS_NOT_REACH:
BJovke03dbafb2016-09-15 13:41:41 +0200246 case GTPIE_BCM:
Harald Weltebed35df2011-11-02 13:06:18 +0100247 if (j < GTPIE_SIZE) {
248 ie[j] = (union gtpie_member *)p;
249 if (GTPIE_DEBUG)
250 printf
251 ("GTPIE TV1 found. Type %d, value %d\n",
252 ie[j]->tv1.t, ie[j]->tv1.v);
253 p += 1 + 1;
254 j++;
255 }
256 break;
257 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 or 4 */
258 case GTPIE_FL_C:
259 if (version != 0) {
260 if (j < GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
261 /* case GTPIE_TEI_DI: gtp1 */
262 /* case GTPIE_TEI_C: gtp1 */
263 ie[j] = (union gtpie_member *)p;
264 if (GTPIE_DEBUG)
265 printf
266 ("GTPIE TV 4 found. Type %d, value %d\n",
267 ie[j]->tv4.t,
268 ie[j]->tv4.v);
269 p += 1 + 4;
270 j++;
271 }
272 break;
273 }
274 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
275 case GTPIE_CHARGING_C:
276 case GTPIE_TRACE_REF:
277 case GTPIE_TRACE_TYPE:
278 if (j < GTPIE_SIZE) {
279 ie[j] = (union gtpie_member *)p;
280 if (GTPIE_DEBUG)
281 printf
282 ("GTPIE TV2 found. Type %d, value %d\n",
283 ie[j]->tv2.t, ie[j]->tv2.v);
284 p += 1 + 2;
285 j++;
286 }
287 break;
288 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
289 case GTPIE_P_TMSI_S:
290 if (j < GTPIE_SIZE) {
291 ie[j] = (union gtpie_member *)p;
292 if (GTPIE_DEBUG)
293 printf
294 ("GTPIE TV 3 found. Type %d, value %d, %d, %d\n",
295 ie[j]->tv0.t, ie[j]->tv0.v[0],
296 ie[j]->tv0.v[1], ie[j]->tv0.v[2]);
297 p += 1 + 3;
298 j++;
299 }
300 break;
301 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
302 case GTPIE_P_TMSI:
303 case GTPIE_CHARGING_ID:
304 /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
305 /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
306 if (j < GTPIE_SIZE) {
307 ie[j] = (union gtpie_member *)p;
308 if (GTPIE_DEBUG)
309 printf
310 ("GTPIE TV 4 found. Type %d, value %d\n",
311 ie[j]->tv4.t, ie[j]->tv4.v);
312 p += 1 + 4;
313 j++;
314 }
315 break;
316 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
317 if (j < GTPIE_SIZE) {
318 ie[j] = (union gtpie_member *)p;
319 if (GTPIE_DEBUG)
320 printf("GTPIE TV 5 found. Type %d\n",
321 ie[j]->tv0.t);
322 p += 1 + 5;
323 j++;
324 }
325 break;
326 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
327 if (j < GTPIE_SIZE) {
328 ie[j] = (union gtpie_member *)p;
329 if (GTPIE_DEBUG)
330 printf("GTPIE TV 7 found. Type %d\n",
331 ie[j]->tv0.t);
332 p += 1 + 7;
333 j++;
334 }
335 break;
336 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
337 if (j < GTPIE_SIZE) {
338 ie[j] = (union gtpie_member *)p;
339 if (GTPIE_DEBUG)
340 printf
341 ("GTPIE_IMSI - GTPIE TV 8 found. Type %d, value 0x%llx\n",
342 ie[j]->tv0.t, ie[j]->tv8.v);
343 p += 1 + 8;
344 j++;
345 }
346 break;
347 case GTPIE_RAI: /* TV GTPIE types with value length 6 */
348 if (j < GTPIE_SIZE) {
349 ie[j] = (union gtpie_member *)p;
350 if (GTPIE_DEBUG)
351 printf
352 ("GTPIE_RAI - GTPIE TV 6 found. Type %d, value 0x%llx\n",
353 ie[j]->tv0.t, ie[j]->tv8.v);
354 p += 1 + 6;
355 j++;
356 }
357 break;
358 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
359 if (j < GTPIE_SIZE) {
360 ie[j] = (union gtpie_member *)p;
361 if (GTPIE_DEBUG)
362 printf("GTPIE TV 28 found. Type %d\n",
363 ie[j]->tv0.t);
364 p += 1 + 28;
365 j++;
366 }
367 break;
368 case GTPIE_EXT_HEADER_T: /* GTP extension header */
369 if (j < GTPIE_SIZE) {
370 ie[j] = (union gtpie_member *)p;
371 if (GTPIE_DEBUG)
372 printf
373 ("GTPIE GTP extension header found. Type %d\n",
374 ie[j]->ext.t);
375 p += 2 + ntoh8(ie[j]->ext.l);
376 j++;
377 }
378 break;
379 case GTPIE_EUA: /* TLV GTPIE types with variable length */
380 case GTPIE_MM_CONTEXT:
381 case GTPIE_PDP_CONTEXT:
382 case GTPIE_APN:
383 case GTPIE_PCO:
384 case GTPIE_GSN_ADDR:
385 case GTPIE_MSISDN:
386 case GTPIE_QOS_PROFILE:
387 case GTPIE_AUTH_QUINTUP:
388 case GTPIE_TFT:
389 case GTPIE_TARGET_INF:
390 case GTPIE_UTRAN_TRANS:
391 case GTPIE_RAB_SETUP:
392 case GTPIE_TRIGGER_ID:
393 case GTPIE_OMC_ID:
394 case GTPIE_CHARGING_ADDR:
395 case GTPIE_RAT_TYPE:
396 case GTPIE_USER_LOC:
397 case GTPIE_MS_TZ:
398 case GTPIE_IMEI_SV:
399 case GTPIE_PRIVATE:
400 if (j < GTPIE_SIZE) {
401 ie[j] = (union gtpie_member *)p;
402 if (GTPIE_DEBUG)
403 printf("GTPIE TLV found. Type %d\n",
404 ie[j]->tlv.t);
405 p += 3 + ntoh16(ie[j]->tlv.l);
406 j++;
407 }
408 break;
409 default:
410 if (GTPIE_DEBUG)
411 printf("GTPIE something unknown. Type %d\n",
412 *p);
413 return EOF; /* We received something unknown */
414 }
415 }
416 if (p == end) {
417 if (GTPIE_DEBUG)
418 printf("GTPIE normal return. %lx %lx\n",
419 (unsigned long)p, (unsigned long)end);
420 return 0; /* We landed at the end of the packet: OK */
421 } else if (!(j < GTPIE_SIZE)) {
422 if (GTPIE_DEBUG)
423 printf("GTPIE too many elements.\n");
424 return EOF; /* We received too many information elements */
425 } else {
426 if (GTPIE_DEBUG)
427 printf("GTPIE exceeded end of packet. %lx %lx\n",
428 (unsigned long)p, (unsigned long)end);
429 return EOF; /* We exceeded the end of the packet: Error */
430 }
431}
432
433int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
434{
435 int i;
436 unsigned char *p;
437 unsigned char *end;
Harald Weltebed35df2011-11-02 13:06:18 +0100438 int iesize;
439
440 p = pack;
441
442 memset(pack, 0, GTPIE_MAX);
443 end = p + GTPIE_MAX;
444 for (i = 1; i < GTPIE_SIZE; i++)
445 if (ie[i] != 0) {
446 if (GTPIE_DEBUG)
447 printf("gtpie_encaps. Type %d\n", i);
Harald Weltebed35df2011-11-02 13:06:18 +0100448 switch (i) {
449 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
450 case GTPIE_REORDER:
451 case GTPIE_MAP_CAUSE:
452 case GTPIE_MS_VALIDATED:
453 case GTPIE_RECOVERY:
454 case GTPIE_SELECTION_MODE:
455 case GTPIE_TEARDOWN:
456 case GTPIE_NSAPI:
457 case GTPIE_RANAP_CAUSE:
458 case GTPIE_RP_SMS:
459 case GTPIE_RP:
460 case GTPIE_MS_NOT_REACH:
BJovke03dbafb2016-09-15 13:41:41 +0200461 case GTPIE_BCM:
Harald Weltebed35df2011-11-02 13:06:18 +0100462 iesize = 2;
463 break;
464 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
465 case GTPIE_FL_C:
466 case GTPIE_PFI:
467 case GTPIE_CHARGING_C:
468 case GTPIE_TRACE_REF:
469 case GTPIE_TRACE_TYPE:
470 iesize = 3;
471 break;
472 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
473 case GTPIE_P_TMSI_S:
474 iesize = 4;
475 break;
476 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
477 case GTPIE_P_TMSI:
478 /* case GTPIE_TEI_DI: only in gtp1 */
479 /* case GTPIE_TEI_C: only in gtp1 */
480 case GTPIE_CHARGING_ID:
481 iesize = 5;
482 break;
483 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
484 iesize = 6;
485 break;
486 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
487 iesize = 8;
488 break;
489 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
490 case GTPIE_RAI:
491 iesize = 9;
492 break;
493 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
494 iesize = 29;
495 break;
496 case GTPIE_EXT_HEADER_T: /* GTP extension header */
497 iesize = 2 + hton8(ie[i]->ext.l);
498 break;
499 case GTPIE_EUA: /* TLV GTPIE types with length length 2 */
500 case GTPIE_MM_CONTEXT:
501 case GTPIE_PDP_CONTEXT:
502 case GTPIE_APN:
503 case GTPIE_PCO:
504 case GTPIE_GSN_ADDR:
505 case GTPIE_MSISDN:
506 case GTPIE_QOS_PROFILE:
507 case GTPIE_AUTH_QUINTUP:
508 case GTPIE_TFT:
509 case GTPIE_TARGET_INF:
510 case GTPIE_UTRAN_TRANS:
511 case GTPIE_RAB_SETUP:
512 case GTPIE_TRIGGER_ID:
513 case GTPIE_OMC_ID:
514 case GTPIE_CHARGING_ADDR:
515 case GTPIE_PRIVATE:
516 iesize = 3 + hton16(ie[i]->tlv.l);
517 break;
518 default:
519 return 2; /* We received something unknown */
520 }
521 if (p + iesize < end) {
522 memcpy(p, ie[i], iesize);
523 p += iesize;
524 *len += iesize;
525 } else
526 return 2; /* Out of space */
527 }
528 return 0;
jjako52c24142002-12-16 13:33:51 +0000529}
530
Harald Weltef54a1f42010-05-04 11:08:38 +0200531int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
Harald Weltebed35df2011-11-02 13:06:18 +0100532 void *pack, unsigned *len)
533{
534 unsigned int i, j;
535 unsigned char *p;
536 unsigned char *end;
Harald Weltebed35df2011-11-02 13:06:18 +0100537 int iesize;
jjako52c24142002-12-16 13:33:51 +0000538
Harald Weltebed35df2011-11-02 13:06:18 +0100539 p = pack;
540
541 memset(pack, 0, GTPIE_MAX);
542 end = p + GTPIE_MAX;
543 for (j = 0; j < GTPIE_SIZE; j++)
544 for (i = 0; i < size; i++)
545 if (ie[i].t == j) {
546 if (GTPIE_DEBUG)
547 printf
548 ("gtpie_encaps. Number %d, Type %d\n",
549 i, ie[i].t);
Harald Weltebed35df2011-11-02 13:06:18 +0100550 switch (ie[i].t) {
551 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
552 case GTPIE_REORDER:
553 case GTPIE_MAP_CAUSE:
554 case GTPIE_MS_VALIDATED:
555 case GTPIE_RECOVERY:
556 case GTPIE_SELECTION_MODE:
557 case GTPIE_TEARDOWN:
558 case GTPIE_NSAPI:
559 case GTPIE_RANAP_CAUSE:
560 case GTPIE_RP_SMS:
561 case GTPIE_RP:
562 case GTPIE_MS_NOT_REACH:
BJovke03dbafb2016-09-15 13:41:41 +0200563 case GTPIE_BCM:
Harald Weltebed35df2011-11-02 13:06:18 +0100564 iesize = 2;
565 break;
566 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
567 case GTPIE_CHARGING_C:
568 case GTPIE_TRACE_REF:
569 case GTPIE_TRACE_TYPE:
570 iesize = 3;
571 break;
572 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
573 case GTPIE_P_TMSI_S:
574 iesize = 4;
575 break;
576 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
577 case GTPIE_P_TMSI:
578 case GTPIE_TEI_DI:
579 case GTPIE_TEI_C:
580 iesize = 5;
581 break;
582 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
583 iesize = 6;
584 break;
585 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
586 iesize = 8;
587 break;
588 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
589 case GTPIE_RAI:
590 iesize = 9;
591 break;
592 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
593 iesize = 29;
594 break;
595 case GTPIE_EXT_HEADER_T: /* GTP extension header */
596 iesize = 2 + hton8(ie[i].ext.l);
597 break;
598 case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */
599 case GTPIE_EUA:
600 case GTPIE_MM_CONTEXT:
601 case GTPIE_PDP_CONTEXT:
602 case GTPIE_APN:
603 case GTPIE_PCO:
604 case GTPIE_GSN_ADDR:
605 case GTPIE_MSISDN:
606 case GTPIE_QOS_PROFILE:
607 case GTPIE_AUTH_QUINTUP:
608 case GTPIE_TFT:
609 case GTPIE_TARGET_INF:
610 case GTPIE_UTRAN_TRANS:
611 case GTPIE_RAB_SETUP:
612 case GTPIE_TRIGGER_ID:
613 case GTPIE_OMC_ID:
614 case GTPIE_CHARGING_ADDR:
615 case GTPIE_PRIVATE:
616 iesize = 3 + hton16(ie[i].tlv.l);
617 break;
618 default:
619 return 2; /* We received something unknown */
620 }
621 if (p + iesize < end) {
622 memcpy(p, &ie[i], iesize);
623 p += iesize;
624 *len += iesize;
625 } else
626 return 2; /* Out of space */
627 }
628 return 0;
jjako52c24142002-12-16 13:33:51 +0000629}