Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/parser/contact/parse_contact.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Contact header field body parser
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of ser, a free SIP server.
7
 *
8
 * ser 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
 * For a license to use the ser software under conditions
14
 * other than those described here, or to purchase support for this
15
 * software, please contact iptel.org by e-mail at the following addresses:
16
 *    info@iptel.org
17
 *
18
 * ser is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26
 *
27
 */
28
29
#include <string.h> /* memset */
30
#include "../hf.h"
31
#include "../../mem/mem.h" /* pkg_malloc, pkg_free */
32
#include "../../dprint.h"
33
#include "../../trim.h" /* trim_leading */
34
#include "parse_contact.h"
35
36
37
static inline int contact_parser(char *_s, int _l, contact_body_t *_c)
38
4.01k
{
39
4.01k
  str tmp;
40
41
4.01k
  tmp.s = _s;
42
4.01k
  tmp.len = _l;
43
44
4.01k
  trim_leading(&tmp);
45
46
4.01k
  if(tmp.len == 0) {
47
30
    LM_ERR("empty body\n");
48
30
    return -1;
49
30
  }
50
51
3.98k
  if(tmp.s[0] == '*') {
52
238
    _c->star = 1;
53
3.75k
  } else {
54
3.75k
    if(parse_contacts(&tmp, &(_c->contacts)) < 0) {
55
593
      LM_ERR("error while parsing contacts\n");
56
593
      return -2;
57
593
    }
58
3.75k
  }
59
60
3.39k
  return 0;
61
3.98k
}
62
63
64
/*
65
 * Parse contact header field body
66
 */
67
int parse_contact(struct hdr_field *_h)
68
4.01k
{
69
4.01k
  contact_body_t *b;
70
71
4.01k
  if(_h->parsed != 0) {
72
0
    return 0; /* Already parsed */
73
0
  }
74
75
4.01k
  b = (contact_body_t *)pkg_malloc(sizeof(contact_body_t));
76
4.01k
  if(b == 0) {
77
0
    PKG_MEM_ERROR;
78
0
    return -1;
79
0
  }
80
81
4.01k
  memset(b, 0, sizeof(contact_body_t));
82
83
4.01k
  if(contact_parser(_h->body.s, _h->body.len, b) < 0) {
84
623
    LM_ERR("error while parsing\n");
85
623
    pkg_free(b);
86
623
    return -2;
87
623
  }
88
89
3.39k
  _h->parsed = (void *)b;
90
3.39k
  return 0;
91
4.01k
}
92
93
94
/*
95
 * Free all memory
96
 */
97
void free_contact(contact_body_t **_c)
98
3.39k
{
99
3.39k
  if(*_c == NULL)
100
0
    return;
101
3.39k
  if((*_c)->contacts) {
102
3.15k
    free_contacts(&((*_c)->contacts));
103
3.15k
  }
104
105
3.39k
  pkg_free(*_c);
106
3.39k
  *_c = 0;
107
3.39k
}
108
109
110
/*
111
 * Print structure, for debugging only
112
 */
113
void print_contact(FILE *_o, contact_body_t *_c)
114
0
{
115
0
  fprintf(_o, "===Contact body===\n");
116
0
  fprintf(_o, "star: %d\n", _c->star);
117
0
  print_contacts(_o, _c->contacts);
118
0
  fprintf(_o, "===/Contact body===\n");
119
0
}
120
121
122
/*
123
 * Contact header field iterator, returns next contact if any, it doesn't
124
 * parse message header if not absolutely necessary
125
 */
126
int contact_iterator(contact_t **c, struct sip_msg *msg, contact_t *prev)
127
0
{
128
0
  static struct hdr_field *hdr = 0;
129
0
  struct hdr_field *last;
130
0
  contact_body_t *cb;
131
132
0
  if(!msg) {
133
0
    LM_ERR("invalid parameter value\n");
134
0
    return -1;
135
0
  }
136
137
0
  if(!prev) {
138
    /* No pointer to previous contact given, find topmost
139
     * contact and return pointer to the first contact
140
     * inside that header field
141
     */
142
0
    hdr = msg->contact;
143
0
    if(!hdr) {
144
0
      if(parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
145
0
        LM_ERR("error while parsing headers\n");
146
0
        return -1;
147
0
      }
148
149
0
      hdr = msg->contact;
150
0
    }
151
152
0
    if(hdr) {
153
0
      if(parse_contact(hdr) < 0) {
154
0
        LM_ERR("error while parsing Contact\n");
155
0
        return -1;
156
0
      }
157
0
    } else {
158
0
      *c = 0;
159
0
      return 1;
160
0
    }
161
162
0
    cb = (contact_body_t *)hdr->parsed;
163
0
    *c = cb->contacts;
164
0
    return 0;
165
0
  } else {
166
    /* Check if there is another contact in the
167
     * same header field and if so then return it
168
     */
169
0
    if(prev->next) {
170
0
      *c = prev->next;
171
0
      return 0;
172
0
    }
173
174
0
    if(hdr == NULL) {
175
0
      LM_ERR("contact iterator not initialized\n");
176
0
      return -1;
177
0
    }
178
179
    /* Try to find and parse another Contact
180
     * header field
181
     */
182
0
    last = hdr;
183
0
    hdr = hdr->next;
184
185
    /* Search another already parsed Contact
186
     * header field
187
     */
188
0
    while(hdr && hdr->type != HDR_CONTACT_T) {
189
0
      hdr = hdr->next;
190
0
    }
191
192
0
    if(!hdr) {
193
      /* Look for another Contact HF in unparsed
194
       * part of the message header
195
       */
196
0
      if(parse_headers(msg, HDR_CONTACT_F, 1) == -1) {
197
0
        LM_ERR("error while parsing message header\n");
198
0
        return -1;
199
0
      }
200
201
      /* Check if last found header field is Contact
202
       * and if it is not the same header field as the
203
       * previous Contact HF (that indicates that the previous
204
       * one was the last header field in the header)
205
       */
206
0
      if((msg->last_header->type == HDR_CONTACT_T)
207
0
          && (msg->last_header != last)) {
208
0
        hdr = msg->last_header;
209
0
      } else {
210
0
        *c = 0;
211
0
        return 1;
212
0
      }
213
0
    }
214
215
0
    if(parse_contact(hdr) < 0) {
216
0
      LM_ERR("error while parsing Contact HF body\n");
217
0
      return -1;
218
0
    }
219
220
    /* And return first contact within that
221
     * header field
222
     */
223
0
    cb = (contact_body_t *)hdr->parsed;
224
0
    *c = cb->contacts;
225
0
    return 0;
226
0
  }
227
0
}
228
229
/**
230
 * Parse all contact headers
231
 */
232
int parse_contact_headers(sip_msg_t *msg)
233
14.2k
{
234
14.2k
  hdr_field_t *hdr;
235
236
14.2k
  if(parse_headers(msg, HDR_EOH_F, 0) < 0) {
237
3.98k
    LM_ERR("failed to parse headers\n");
238
3.98k
    return -1;
239
3.98k
  }
240
241
10.2k
  if(msg->contact) {
242
1.63k
    hdr = msg->contact;
243
5.32k
    while(hdr) {
244
4.31k
      if(hdr->type == HDR_CONTACT_T) {
245
4.01k
        if(!hdr->parsed && (parse_contact(hdr) < 0)) {
246
623
          LM_ERR("failed to parse Contact body\n");
247
623
          return -1;
248
623
        }
249
4.01k
      }
250
3.69k
      hdr = hdr->next;
251
3.69k
    }
252
1.63k
  }
253
254
9.64k
  return 0;
255
10.2k
}
256
257
/**
258
 * Parse first contact header
259
 */
260
int parse_contact_header(sip_msg_t *msg)
261
0
{
262
0
  if(!msg->contact
263
0
      && (parse_headers(msg, HDR_CONTACT_F, 0) == -1 || !msg->contact)) {
264
0
    LM_DBG("bad msg or missing CONTACT header\n");
265
0
    return -1;
266
0
  }
267
268
0
  if(msg->contact->parsed)
269
0
    return 0;
270
271
0
  return parse_contact(msg->contact);
272
0
}