Coverage Report

Created: 2025-08-28 06:16

/src/opensips/parser/sdp/sdp_helpr_funcs.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * SDP parser helpers
3
 *
4
 * Copyright (C) 2008 SOMA Networks, INC.
5
 *
6
 * This file is part of opensips, a free SIP server.
7
 *
8
 * opensips is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version
12
 *
13
 * opensips is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 *
23
 * History:
24
 * --------
25
 * 2007-09-09 ported helper functions from nathelper module (osas)
26
 * 2008-04-22 integrated RFC4975 attributes - patch provided by Denis Bilenko (denik)
27
 *
28
 */
29
30
31
#include "../../ut.h"
32
#include "../msg_parser.h"
33
#include "../parser_f.h"
34
#include "../parse_hname2.h"
35
#include "sdp.h"
36
37
38
static struct {
39
  const char *s;
40
  int len;
41
  int is_rtp;
42
} sup_ptypes[] = {
43
  {.s = "rtp/avp",   .len = 7, .is_rtp = 1},
44
  {.s = "udptl",     .len = 5, .is_rtp = 0},
45
  {.s = "rtp/avpf",  .len = 8, .is_rtp = 1},
46
  {.s = "rtp/savp",  .len = 8, .is_rtp = 1},
47
  {.s = "rtp/savpf", .len = 9, .is_rtp = 1},
48
  {.s = "udp",       .len = 3, .is_rtp = 0},
49
  {.s = "udp/bfcp",  .len = 8, .is_rtp = 0},
50
  {.s = NULL,        .len = 0, .is_rtp = 0}
51
};
52
53
54
int extract_rtpmap(str *body,
55
  str *rtpmap_payload, str *rtpmap_encoding, str *rtpmap_clockrate, str *rtpmap_parmas)
56
0
{
57
0
  char *cp, *cp1;
58
0
  int len;
59
60
  /* a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>] */
61
  /* 1       9            10              12           14 */
62
0
  if (body->len < 14)
63
0
    return -1;
64
65
0
  if (strncasecmp(body->s, "a=rtpmap:", 9) !=0) {
66
    /*LM_DBG("We are not pointing to an a=rtpmap: attribute =>`%.*s'\n", body->len, body->s); */
67
0
    return -1;
68
0
  }
69
70
0
  cp1 = body->s;
71
72
0
  rtpmap_payload->s = cp1 + 9; /* skip `a=rtpmap:' */
73
0
  rtpmap_payload->len = eat_line(rtpmap_payload->s, body->s + body->len -
74
0
            rtpmap_payload->s) - rtpmap_payload->s;
75
0
  trim_len(rtpmap_payload->len, rtpmap_payload->s, *rtpmap_payload);
76
0
  len = rtpmap_payload->len;
77
78
  /* */
79
0
  cp = eat_token_end(rtpmap_payload->s, rtpmap_payload->s + rtpmap_payload->len);
80
0
  rtpmap_payload->len = cp - rtpmap_payload->s;
81
0
  if (rtpmap_payload->len <= 0 || cp == rtpmap_payload->s) {
82
0
    LM_ERR("no encoding in `a=rtpmap'\n");
83
0
    return -1;
84
0
  }
85
0
  len -= rtpmap_payload->len;
86
0
  rtpmap_encoding->s = cp;
87
0
  cp = eat_space_end(rtpmap_encoding->s, rtpmap_encoding->s + len);
88
0
  len -= cp - rtpmap_encoding->s;
89
0
  if (len <= 0 || cp == rtpmap_encoding->s) {
90
0
    LM_ERR("no encoding in `a=rtpmap:'\n");
91
0
    return -1;
92
0
  }
93
94
0
  rtpmap_encoding->s = cp;
95
0
  cp1 = (char*)l_memmem(cp, "/", len, 1);
96
0
  len -= cp1 - cp;
97
0
  if (cp1==NULL || len <= 1 || cp == cp1) {
98
0
    LM_ERR("invalid encoding in `a=rtpmap' [%.*s]\n",
99
0
      rtpmap_payload->len,rtpmap_payload->s);
100
0
    return -1;
101
0
  }
102
0
  rtpmap_encoding->len = cp1 - cp;
103
104
  /* skip the '/' char */
105
0
  cp = cp1+1;
106
0
  len--;
107
108
0
  cp1 = (char*)l_memmem(cp, "/", len, 1);
109
0
  if (cp1 == NULL) {
110
0
    rtpmap_clockrate->s = cp;
111
0
    rtpmap_clockrate->len = len;
112
0
    rtpmap_parmas->s = NULL;
113
0
    rtpmap_parmas->len = 0;
114
0
  } else {
115
0
    rtpmap_clockrate->s = cp;
116
0
    rtpmap_clockrate->len = cp1-cp;
117
0
    len -= cp1 - cp;
118
0
    if (len <= 1) {
119
0
      LM_ERR("invalid encoding in `a=rtpmap' [%.*s]\n",
120
0
        rtpmap_payload->len,rtpmap_payload->s);
121
0
      return -1;
122
0
    }
123
0
    rtpmap_parmas->s = cp1 + 1;
124
0
    rtpmap_parmas->len = len - 1;
125
0
  }
126
0
  return 0;
127
0
}
128
129
int extract_custom_a_attr(str *body, str *payload, str *value)
130
0
{
131
0
  char *cp, *p;
132
0
  int len,i;
133
134
  /* a=<format> <format specific parameters> */
135
  /* 10 for good luck ? */
136
0
  if (body->len < 10) {
137
0
    LM_DBG("Too small body \n");
138
0
    return -1;
139
0
  }
140
141
0
  if (body->s[0] != 'a' && body->s[1] != '=') {
142
0
    LM_DBG("We are not pointing to an a= attribute =>`%.*s'\n", body->len, body->s);
143
0
    return -1;
144
0
  }
145
146
0
  i=0;
147
0
  p=body->s;
148
0
  while (i<body->len) {
149
0
    if (*p == ':')
150
0
      break;
151
0
    p++;
152
0
    i++;
153
0
  }
154
155
0
  if (i==body->len) {
156
    /* no payload found */
157
0
    LM_DBG("no payload ID\n");
158
0
    return -1;
159
0
  }
160
161
  /* payload ID starts after : */
162
0
  payload->s = p+1;
163
0
  payload->len = eat_line(payload->s, body->s + body->len -
164
0
    payload->s) - payload->s;
165
0
  trim_len(payload->len, payload->s, *payload);
166
0
  len = payload->len;
167
168
  /* */
169
0
  cp = eat_token_end(payload->s, payload->s + payload->len);
170
0
  payload->len = cp - payload->s;
171
0
  if (payload->len <= 0 || cp == payload->s) {
172
0
    LM_ERR("no encoding \n");
173
0
    return -1;
174
0
  }
175
176
0
  len -= payload->len;
177
0
  value->s = cp;
178
0
  cp = eat_space_end(value->s, value->s + len);
179
0
  len -= cp - value->s;
180
0
  if (len <= 0 || cp == value->s) {
181
0
    LM_DBG("no value in a= line \n");
182
0
    return -1;
183
0
  }
184
185
0
  value->s = cp;
186
187
0
  value->len = eat_line(value->s, body->s + body->len -
188
0
    value->s) - value->s;
189
0
  trim_len(value->len, value->s, *value);
190
191
0
  return 0;
192
0
}
193
194
int extract_fmtp( str *body, str *fmtp_payload, str *fmtp_string )
195
0
{
196
0
  char *cp, *cp1;
197
0
  int len;
198
199
  /* a=fmtp:<format> <format specific parameters> */
200
  /* 1     7       8                           10 */
201
0
  if (body->len < 10)
202
0
    return -1;
203
204
0
  if (strncasecmp(body->s, "a=fmtp:", 7) !=0) {
205
    /*LM_DBG("We are not pointing to an a=fmtp: attribute =>`%.*s'\n", body->len, body->s); */
206
0
    return -1;
207
0
  }
208
209
0
  cp1 = body->s;
210
211
0
  fmtp_payload->s = cp1 + 7; /* skip `a=fmtp:' */
212
0
  fmtp_payload->len = eat_line(fmtp_payload->s, body->s + body->len -
213
0
    fmtp_payload->s) - fmtp_payload->s;
214
0
  trim_len(fmtp_payload->len, fmtp_payload->s, *fmtp_payload);
215
0
  len = fmtp_payload->len;
216
217
  /* */
218
0
  cp = eat_token_end(fmtp_payload->s, fmtp_payload->s + fmtp_payload->len);
219
0
  fmtp_payload->len = cp - fmtp_payload->s;
220
0
  if (fmtp_payload->len <= 0 || cp == fmtp_payload->s) {
221
0
    LM_ERR("no encoding in `a=fmtp:'\n");
222
0
    return -1;
223
0
  }
224
0
  len -= fmtp_payload->len;
225
0
  fmtp_string->s = cp;
226
0
  cp = eat_space_end(fmtp_string->s, fmtp_string->s + len);
227
0
  len -= cp - fmtp_string->s;
228
0
  if (len <= 0 || cp == fmtp_string->s) {
229
0
    LM_ERR("no encoding in `a=fmtp:'\n");
230
0
    return -1;
231
0
  }
232
233
0
  fmtp_string->s = cp;
234
235
0
  fmtp_string->len = eat_line(fmtp_string->s, body->s + body->len -
236
0
    fmtp_string->s) - fmtp_string->s;
237
0
  trim_len(fmtp_string->len, fmtp_string->s, *fmtp_string);
238
239
0
  return 0;
240
0
}
241
242
/* generic method for attribute extraction
243
 * field must has format "a=attrname:" */
244
int extract_field(str *body, str *value, str field)
245
0
{
246
0
  if (body->len < field.len)
247
0
    return -1;
248
0
  if (memcmp(body->s, field.s, field.len) !=0) {
249
    /*LM_DBG("We are not pointing to an %.* attribute =>`%.*s'\n", field.len, field.s, body->len, body->s); */
250
0
    return -1;
251
0
  }
252
253
0
  value->s = body->s + field.len; /* skip `a=attrname:' */
254
0
  value->len = eat_line(value->s, body->s + body->len -
255
0
            value->s) - value->s;
256
0
  trim_len(value->len, value->s, *value);
257
258
0
  return 0;
259
0
}
260
261
262
int extract_ptime(str *body, str *ptime)
263
0
{
264
0
  static const str field = str_init("a=ptime:");
265
0
  return extract_field(body, ptime, field);
266
0
}
267
268
int extract_accept_types(str *body, str *accept_types)
269
0
{
270
0
  static const str field = str_init("a=accept-types:");
271
0
  return extract_field(body, accept_types, field);
272
0
}
273
274
int extract_accept_wrapped_types(str *body, str *accept_wrapped_types)
275
0
{
276
0
  static const str field = str_init("a=accept-wrapped-types:");
277
0
  return extract_field(body, accept_wrapped_types, field);
278
0
}
279
280
int extract_max_size(str *body, str *max_size)
281
0
{
282
0
  static const str field = str_init("a=max-size:");
283
0
  return extract_field(body, max_size, field);
284
0
}
285
286
int extract_path(str *body, str *path)
287
0
{
288
0
  static const str field = str_init("a=path:");
289
0
  return extract_field(body, path, field);
290
0
}
291
292
int extract_rtcp(str *body, str *rtcp)
293
0
{
294
0
  static const str field = str_init("a=rtcp:");
295
0
  return extract_field(body, rtcp, field);
296
0
}
297
298
int extract_sendrecv_mode(str *body, str *sendrecv_mode, int *is_on_hold)
299
0
{
300
0
  char *cp1;
301
302
0
  if (body->len < 10)
303
0
    return -1;
304
305
0
  cp1 = body->s;
306
0
  if ( !( (strncasecmp(cp1, "a=sendrecv", 10) == 0) ||
307
0
    (strncasecmp(cp1, "a=recvonly", 10) == 0))) {
308
0
    if ( !( (strncasecmp(cp1, "a=inactive", 10) == 0) ||
309
0
      (strncasecmp(cp1, "a=sendonly", 10) == 0) )) {
310
0
      return -1;
311
0
    } else {
312
0
      *is_on_hold = RFC3264_HOLD;
313
0
    }
314
0
  }
315
316
0
  sendrecv_mode->s = body->s + 2; /* skip `a=' */
317
0
  sendrecv_mode->len = 8; /* we know the length and therefore we don't need to overkill */
318
  /*
319
  sendrecv_mode->len = eat_line(sendrecv_mode->s, body->s + body->len -
320
    sendrecv_mode->s) - sendrecv_mode->s;
321
  trim_len(sendrecv_mode->len, sendrecv_mode->s, *sendrecv_mode);
322
  */
323
324
0
  return 0;
325
0
}
326
327
int extract_bwidth(str *body, str *bwtype, str *bwwitdth)
328
0
{
329
0
  char *cp, *cp1;
330
0
  int len;
331
332
0
  cp1 = NULL;
333
0
  for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
334
0
    cp1 = (char*)l_memmem(cp, "b=", len, 2);
335
0
    if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
336
0
      break;
337
0
    cp = cp1 + 2;
338
0
  }
339
0
  if (cp1 == NULL)
340
0
    return -1;
341
342
0
  bwtype->s = cp1 + 2;
343
0
  bwtype->len = eat_line(bwtype->s, body->s + body->len - bwtype->s) - bwtype->s;
344
0
  trim_len(bwtype->len, bwtype->s, *bwtype);
345
346
0
  cp = bwtype->s;
347
0
  len = bwtype->len;
348
0
  cp1 = (char*)l_memmem(cp, ":", len, 1);
349
0
  len -= cp1 - cp;
350
0
  if (len <= 0) {
351
0
    LM_ERR("invalid encoding in `b=%.*s'\n", bwtype->len, bwtype->s);
352
0
    return -1;
353
0
  }
354
0
  bwtype->len = cp1 - cp;
355
356
  /* skip ':' */
357
0
  bwwitdth->s = cp1 + 1;
358
0
  bwwitdth->len = len - 1;
359
360
0
  return 0;
361
0
}
362
363
int extract_mediaip(str *body, str *mediaip, int *pf, char *line)
364
0
{
365
0
  char *cp, *cp1;
366
0
  int len, nextisip;
367
368
0
  cp1 = NULL;
369
0
  for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
370
0
    cp1 = (char*)l_memmem(cp, line, len, 2);
371
0
    if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
372
0
      break;
373
0
    cp = cp1 + 2;
374
0
  }
375
0
  if (cp1 == NULL)
376
0
    return -1;
377
378
0
  mediaip->s = cp1 + 2;
379
0
  mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
380
0
  trim_len(mediaip->len, mediaip->s, *mediaip);
381
382
0
  nextisip = 0;
383
0
  for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
384
0
    len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
385
0
    if (nextisip == 1) {
386
0
      mediaip->s = cp;
387
0
      mediaip->len = len;
388
0
      nextisip++;
389
0
      break;
390
0
    }
391
0
    if (len == 3 && memcmp(cp, "IP", 2) == 0) {
392
0
      switch (cp[2]) {
393
0
      case '4':
394
0
        nextisip = 1;
395
0
        *pf = AF_INET;
396
0
        break;
397
398
0
      case '6':
399
0
        nextisip = 1;
400
0
        *pf = AF_INET6;
401
0
        break;
402
403
0
      default:
404
0
        break;
405
0
      }
406
0
    }
407
    /* consume all spaces starting from the second char after the token
408
       First char after the token is the char that stoped the token
409
       parsing, so it is space or \r / \n, so we simply skip it */
410
0
    cp = eat_space_end(cp + len + 1, mediaip->s + mediaip->len);
411
0
  }
412
0
  if (nextisip != 2 || mediaip->len == 0) {
413
0
    LM_ERR("no `IP[4|6]' in `%s' field\n",line);
414
0
    return -1;
415
0
  }
416
0
  return 1;
417
0
}
418
419
int extract_media_attr(str *body, str *mediamedia, str *mediaport, str *mediatransport, str *mediapayload, int *is_rtp)
420
0
{
421
0
  char *cp, *cp1;
422
0
  int len, i;
423
424
0
  cp1 = NULL;
425
0
  for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
426
0
    cp1 = (char*)l_memmem(cp, "m=", len, 2);
427
0
    if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
428
0
      break;
429
0
    cp = cp1 + 2;
430
0
  }
431
0
  if (cp1 == NULL) {
432
0
    LM_ERR("no `m=' in SDP\n");
433
0
    return -1;
434
0
  }
435
0
  mediaport->s = cp1 + 2; /* skip `m=' */
436
0
  mediaport->len = eat_line(mediaport->s, body->s + body->len -
437
0
    mediaport->s) - mediaport->s;
438
0
  trim_len(mediaport->len, mediaport->s, *mediaport);
439
440
0
  mediapayload->len = mediaport->len;
441
0
  mediamedia->s = mediaport->s;
442
443
444
  /* Skip media supertype and spaces after it */
445
0
  cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
446
0
  mediaport->len -= cp - mediaport->s;
447
0
  mediamedia->len = mediapayload->len - mediaport->len;
448
0
  if (mediaport->len <= 0 || cp == mediaport->s) {
449
0
    LM_ERR("no port in `m='\n");
450
0
    return -1;
451
0
  }
452
0
  mediaport->s = cp;
453
454
0
  cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len);
455
0
  mediaport->len -= cp - mediaport->s;
456
0
  if (mediaport->len <= 0 || cp == mediaport->s) {
457
0
    LM_ERR("no port in `m='\n");
458
0
    return -1;
459
0
  }
460
461
  /* Extract port */
462
0
  mediaport->s = cp;
463
0
  cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
464
0
  mediatransport->len = mediaport->len - (cp - mediaport->s);
465
  /* coverity[copy_paste_error] false positive CID #40557 */
466
0
  if (mediatransport->len <= 0 || cp == mediaport->s) {
467
0
    LM_ERR("no port in `m='\n");
468
0
    return -1;
469
0
  }
470
0
  mediatransport->s = cp;
471
0
  mediaport->len = cp - mediaport->s;
472
473
  /* Skip spaces after port */
474
0
  cp = eat_space_end(mediatransport->s, mediatransport->s + mediatransport->len);
475
0
  mediatransport->len -= cp - mediatransport->s;
476
0
  if (mediatransport->len <= 0 || cp == mediatransport->s) {
477
0
    LM_ERR("no protocol type in `m='\n");
478
0
    return -1;
479
0
  }
480
  /* Extract protocol type */
481
0
  mediatransport->s = cp;
482
0
  cp = eat_token_end(mediatransport->s, mediatransport->s + mediatransport->len);
483
0
  if (cp == mediatransport->s) {
484
0
    LM_ERR("no protocol type in `m='\n");
485
0
    return -1;
486
0
  }
487
0
  mediatransport->len = cp - mediatransport->s;
488
489
0
  mediapayload->s = mediatransport->s + mediatransport->len;
490
0
  mediapayload->len -= mediapayload->s - mediamedia->s;
491
0
  cp = eat_space_end(mediapayload->s, mediapayload->s + mediapayload->len);
492
0
  mediapayload->len -= cp - mediapayload->s;
493
0
  mediapayload->s = cp;
494
495
0
  for (i = 0; sup_ptypes[i].s != NULL; i++)
496
0
    if (mediatransport->len == sup_ptypes[i].len &&
497
0
        strncasecmp(mediatransport->s, sup_ptypes[i].s, mediatransport->len) == 0) {
498
0
      *is_rtp = sup_ptypes[i].is_rtp;
499
0
      return 0;
500
0
    }
501
  /* Unproxyable protocol type. Generally it isn't error. */
502
0
  return 0;
503
0
}
504
505
506
/*
507
 * Auxiliary for some functions.
508
 * Returns pointer to first character of found line, or NULL if no such line.
509
 */
510
511
char *find_sdp_line(char* p, char* plimit, char linechar)
512
0
{
513
0
  static char linehead[3] = "x=";
514
0
  char *cp, *cp1;
515
0
  linehead[0] = linechar;
516
  /* Iterate through body */
517
0
  cp = p;
518
0
  for (;;) {
519
0
    if (cp >= plimit)
520
0
      return NULL;
521
0
    cp1 = l_memmem(cp, linehead, plimit-cp, 2);
522
0
    if (cp1 == NULL)
523
0
      return NULL;
524
    /*
525
     * As it is body, we assume it has previous line and we can
526
     * lookup previous character.
527
     */
528
0
    if (cp1[-1] == '\n' || cp1[-1] == '\r')
529
0
      return cp1;
530
    /*
531
     * Having such data, but not at line beginning.
532
     * Skip them and reiterate. l_memmem() will find next
533
     * occurence.
534
     */
535
0
    if (plimit - cp1 < 2)
536
0
      return NULL;
537
0
    cp = cp1 + 2;
538
0
  }
539
0
}
540
541
542
543
/*
544
 * Auxiliary for some functions.
545
 * Returns pointer to first character of found line, or NULL if no such line.
546
 */
547
548
char *find_sdp_line_complex(char* p, char* plimit, char * name)
549
0
{
550
0
  char *cp, *cp1;
551
0
  int len =  strlen(name);
552
553
  /* Iterate through body */
554
0
  cp = p;
555
0
  for (;;) {
556
0
    if (cp >= plimit)
557
0
      return NULL;
558
0
    cp1 = l_memmem(cp, name, plimit-cp, len);
559
0
    if (cp1 == NULL)
560
0
      return NULL;
561
    /*
562
     * As it is body, we assume it has previous line and we can
563
     * lookup previous character.
564
     */
565
0
    if (cp1[-1] == '\n' || cp1[-1] == '\r')
566
0
      return cp1;
567
    /*
568
     * Having such data, but not at line beginning.
569
     * Skip them and reiterate. l_memmem() will find next
570
     * occurence.
571
     */
572
0
    if (plimit - cp1 < 2)
573
0
      return NULL;
574
0
    cp = cp1 + 2;
575
0
  }
576
0
}
577
578
579
/* This function assumes p points to a line of requested type. */
580
char * find_next_sdp_line(char* p, char* plimit, char linechar, char* defptr)
581
0
{
582
0
  char *t;
583
0
  if (p >= plimit || plimit - p < 3)
584
0
    return defptr;
585
0
  t = find_sdp_line(p + 2, plimit, linechar);
586
0
  return t ? t : defptr;
587
0
}
588
589
590
/* returns pointer to next header line, and fill hdr_f ;
591
 * if at end of header returns pointer to the last crlf  (always buf)*/
592
char* get_sdp_hdr_field(char* buf, char* end, struct hdr_field* hdr)
593
0
{
594
595
0
  char* tmp;
596
0
  char *match;
597
598
0
  if ((*buf)=='\n' || (*buf)=='\r'){
599
    /* double crlf or lflf or crcr */
600
0
    hdr->type=HDR_EOH_T;
601
0
    return buf;
602
0
  }
603
604
0
  tmp=parse_hname2(buf, end, hdr);
605
0
  if (hdr->type==HDR_ERROR_T){
606
0
    LM_ERR("bad header\n");
607
0
    goto error;
608
0
  }
609
610
  /* eliminate leading whitespace */
611
0
  tmp=eat_lws_end(tmp, end);
612
0
  if (tmp>=end) {
613
0
    LM_ERR("hf empty\n");
614
0
    goto error;
615
0
  }
616
617
  /* if header-field well-known, parse it, find its end otherwise ;
618
   * after leaving the hdr->type switch, tmp should be set to the
619
   * next header field
620
   */
621
0
  switch(hdr->type){
622
0
    case HDR_CONTENTTYPE_T:
623
0
    case HDR_CONTENTDISPOSITION_T:
624
      /* just skip over it */
625
0
      hdr->body.s=tmp;
626
      /* find end of header */
627
      /* find lf */
628
0
      do{
629
0
        match=q_memchr(tmp, '\n', end-tmp);
630
0
        if (match){
631
0
          match++;
632
0
        }else {
633
0
          LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type);
634
0
          tmp=end;
635
0
          goto error;
636
0
        }
637
0
        tmp=match;
638
0
      }while( match<end &&( (*match==' ')||(*match=='\t') ) );
639
0
      tmp=match;
640
0
      hdr->body.len=match-hdr->body.s;
641
0
      break;
642
0
    default:
643
0
      LM_CRIT("unknown header type %d\n", hdr->type);
644
0
      goto error;
645
0
  }
646
  /* jku: if \r covered by current length, shrink it */
647
0
  trim_r( hdr->body );
648
0
  hdr->len=tmp-hdr->name.s;
649
0
  return tmp;
650
0
error:
651
0
  LM_DBG("error exit\n");
652
0
  hdr->type=HDR_ERROR_T;
653
0
  hdr->len=tmp-hdr->name.s;
654
0
  return tmp;
655
0
}
656