Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/proxy.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * proxy list & assoc. functions
3
 *
4
 * Copyright (C) 2001-2003 FhG Fokus
5
 *
6
 * This file is part of Kamailio, a free SIP server.
7
 *
8
 * Kamailio 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
 * Kamailio 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
/*!
24
 * \file
25
 * \brief Kamailio core :: proxy list & assoc. functions
26
 * \ingroup core
27
 * Module: \ref core
28
 */
29
30
31
#include "config.h"
32
#include "proxy.h"
33
#include "error.h"
34
#include "dprint.h"
35
#include "mem/mem.h"
36
#include "mem/shm_mem.h"
37
38
#include <string.h>
39
#include <stdlib.h>
40
#include <sys/socket.h>
41
42
#ifdef DNS_IP_HACK
43
#include "ut.h"
44
#endif
45
46
#include "resolve.h"
47
#include "ip_addr.h"
48
#include "globals.h"
49
50
51
struct proxy_l *proxies = 0;
52
53
54
/* searches for the proxy named 'name', on port 'port' with
55
   proto 'proto'; if proto==0 => proto wildcard (will match any proto)
56
   returns: pointer to proxy_l on success or 0 if not found */
57
static struct proxy_l *find_proxy(str *name, unsigned short port, int proto)
58
0
{
59
0
  struct proxy_l *t;
60
0
  for(t = proxies; t; t = t->next)
61
0
    if(((t->name.len == name->len)
62
0
           && ((proto == PROTO_NONE) || (t->proto == proto))
63
0
           && (strncasecmp(t->name.s, name->s, name->len) == 0))
64
0
        && (t->port == port))
65
0
      break;
66
0
  return t;
67
0
}
68
69
70
#define HOSTENT_CPY(dst, src, he_malloc, he_free)                            \
71
0
  do {                                                                     \
72
0
    unsigned len, len2;                                                  \
73
0
    int r, i;                                                            \
74
0
                                                                             \
75
0
    /* start copying the host entry.. */                                 \
76
0
    /* copy h_name */                                                    \
77
0
    len = strlen(src->h_name) + 1;                                       \
78
0
    dst->h_name = (char *)he_malloc(sizeof(char) * len);                 \
79
0
    if(dst->h_name)                                                      \
80
0
      strncpy(dst->h_name, src->h_name, len);                          \
81
0
    else {                                                               \
82
0
      ser_error = ret = E_OUT_OF_MEM;                                  \
83
0
      goto error;                                                      \
84
0
    }                                                                    \
85
0
                                                                             \
86
0
    /* copy h_aliases */                                                 \
87
0
    len = 0;                                                             \
88
0
    if(src->h_aliases)                                                   \
89
0
      for(; src->h_aliases[len]; len++)                                \
90
0
        ;                                                            \
91
0
    dst->h_aliases = (char **)he_malloc(sizeof(char *) * (len + 1));     \
92
0
    if(dst->h_aliases == 0) {                                            \
93
0
      ser_error = ret = E_OUT_OF_MEM;                                  \
94
0
      he_free(dst->h_name);                                            \
95
0
      goto error;                                                      \
96
0
    }                                                                    \
97
0
    memset((void *)dst->h_aliases, 0, sizeof(char *) * (len + 1));       \
98
0
    for(i = 0; i < len; i++) {                                           \
99
0
      len2 = strlen(src->h_aliases[i]) + 1;                            \
100
0
      dst->h_aliases[i] = (char *)he_malloc(sizeof(char) * len2);      \
101
0
      if(dst->h_aliases == 0) {                                        \
102
0
        ser_error = ret = E_OUT_OF_MEM;                              \
103
0
        he_free(dst->h_name);                                        \
104
0
        for(r = 0; r < i; r++)                                       \
105
0
          he_free(dst->h_aliases[r]);                              \
106
0
        he_free(dst->h_aliases);                                     \
107
0
        goto error;                                                  \
108
0
      }                                                                \
109
0
      strncpy(dst->h_aliases[i], src->h_aliases[i], len2);             \
110
0
    }                                                                    \
111
0
    /* copy h_addr_list */                                               \
112
0
    len = 0;                                                             \
113
0
    if(src->h_addr_list)                                                 \
114
0
      for(; src->h_addr_list[len]; len++)                              \
115
0
        ;                                                            \
116
0
    dst->h_addr_list = (char **)he_malloc(sizeof(char *) * (len + 1));   \
117
0
    if(dst->h_addr_list == 0) {                                          \
118
0
      ser_error = ret = E_OUT_OF_MEM;                                  \
119
0
      he_free(dst->h_name);                                            \
120
0
      for(r = 0; dst->h_aliases[r]; r++)                               \
121
0
        he_free(dst->h_aliases[r]);                                  \
122
0
      he_free(dst->h_aliases[r]);                                      \
123
0
      he_free(dst->h_aliases);                                         \
124
0
      goto error;                                                      \
125
0
    }                                                                    \
126
0
    memset((void *)dst->h_addr_list, 0, sizeof(char *) * (len + 1));     \
127
0
    for(i = 0; i < len; i++) {                                           \
128
0
      dst->h_addr_list[i] =                                            \
129
0
          (char *)he_malloc(sizeof(char) * src->h_length);         \
130
0
      if(dst->h_addr_list[i] == 0) {                                   \
131
0
        ser_error = ret = E_OUT_OF_MEM;                              \
132
0
        he_free(dst->h_name);                                        \
133
0
        for(r = 0; dst->h_aliases[r]; r++)                           \
134
0
          he_free(dst->h_aliases[r]);                              \
135
0
        he_free(dst->h_aliases[r]);                                  \
136
0
        he_free(dst->h_aliases);                                     \
137
0
        for(r = 0; r < i; r++)                                       \
138
0
          he_free(dst->h_addr_list[r]);                            \
139
0
        he_free(dst->h_addr_list);                                   \
140
0
        goto error;                                                  \
141
0
      }                                                                \
142
0
      memcpy(dst->h_addr_list[i], src->h_addr_list[i], src->h_length); \
143
0
    }                                                                    \
144
0
                                                                             \
145
0
    /* copy h_addr_type & length */                                      \
146
0
    dst->h_addrtype = src->h_addrtype;                                   \
147
0
    dst->h_length = src->h_length;                                       \
148
0
    /*finished hostent copy */                                           \
149
0
                                                                             \
150
0
    return 0;                                                            \
151
0
  } while(0)
152
153
154
#define FREE_HOSTENT(dst, he_free)                 \
155
0
  do {                                           \
156
0
    int r;                                     \
157
0
    if(dst->h_name)                            \
158
0
      he_free(dst->h_name);                  \
159
0
    if(dst->h_aliases) {                       \
160
0
      for(r = 0; dst->h_aliases[r]; r++) {   \
161
0
        he_free(dst->h_aliases[r]);        \
162
0
      }                                      \
163
0
      he_free(dst->h_aliases);               \
164
0
    }                                          \
165
0
    if(dst->h_addr_list) {                     \
166
0
      for(r = 0; dst->h_addr_list[r]; r++) { \
167
0
        he_free(dst->h_addr_list[r]);      \
168
0
      }                                      \
169
0
      he_free(dst->h_addr_list);             \
170
0
    }                                          \
171
0
  } while(0)
172
173
174
/* copies a hostent structure*, returns 0 on success, <0 on error*/
175
static int hostent_cpy(struct hostent *dst, struct hostent *src)
176
0
{
177
0
  int ret;
178
0
  HOSTENT_CPY(dst, src, pkg_malloc, pkg_free);
179
0
error:
180
0
  PKG_MEM_CRITICAL;
181
0
  return ret;
182
0
}
183
184
185
static int hostent_shm_cpy(struct hostent *dst, struct hostent *src)
186
0
{
187
0
  int ret;
188
0
  HOSTENT_CPY(dst, src, shm_malloc, shm_free);
189
0
error:
190
0
  SHM_MEM_CRITICAL;
191
0
  return ret;
192
0
}
193
194
195
void free_hostent(struct hostent *dst)
196
0
{
197
0
  FREE_HOSTENT(dst, pkg_free);
198
0
}
199
200
void free_shm_hostent(struct hostent *dst)
201
0
{
202
0
  FREE_HOSTENT(dst, shm_free);
203
0
}
204
205
206
struct proxy_l *add_proxy(str *name, unsigned short port, int proto)
207
0
{
208
0
  struct proxy_l *p;
209
210
0
  if((p = find_proxy(name, port, proto)) != 0)
211
0
    return p;
212
0
  if((p = mk_proxy(name, port, proto)) == 0)
213
0
    goto error;
214
  /* add p to the proxy list */
215
0
  p->next = proxies;
216
0
  proxies = p;
217
0
  return p;
218
219
0
error:
220
0
  return 0;
221
0
}
222
223
#define MK_PROXY(name, port, protocol, p_malloc, p_free, he_cpy) \
224
0
  do {                                                         \
225
0
    struct proxy_l *p;                                       \
226
0
    struct hostent *he;                                      \
227
0
    char proto;                                              \
228
0
                                                                 \
229
0
    p = (struct proxy_l *)p_malloc(sizeof(struct proxy_l));  \
230
0
    if(p == 0) {                                             \
231
0
      ser_error = E_OUT_OF_MEM;                            \
232
0
      LM_ERR("memory allocation failure\n");               \
233
0
      goto error;                                          \
234
0
    }                                                        \
235
0
    memset(p, 0, sizeof(struct proxy_l));                    \
236
0
    p->name = *name;                                         \
237
0
    p->port = port;                                          \
238
0
                                                                 \
239
0
    LM_DBG("doing DNS lookup...\n");                         \
240
0
    proto = protocol;                                        \
241
0
    he = sip_resolvehost(name, &(p->port), &proto);          \
242
0
    if(he == 0) {                                            \
243
0
      ser_error = E_BAD_ADDRESS;                           \
244
0
      LM_CRIT("could not resolve hostname:"                \
245
0
          " \"%.*s\"\n",                               \
246
0
          name->len, name->s);                         \
247
0
      p_free(p);                                           \
248
0
      goto error;                                          \
249
0
    }                                                        \
250
0
    if(he_cpy(&(p->host), he) != 0) {                        \
251
0
      p_free(p);                                           \
252
0
      goto error;                                          \
253
0
    }                                                        \
254
0
    p->proto = proto;                                        \
255
0
    p->ok = 1;                                               \
256
0
    return p;                                                \
257
0
  error:                                                       \
258
0
    return 0;                                                \
259
0
                                                                 \
260
0
  } while(0)
261
262
/* same as add_proxy, but it doesn't add the proxy to the list
263
 * uses also SRV if possible & port==0 (quick hack) */
264
265
struct proxy_l *mk_proxy(str *name, unsigned short port, int protocol)
266
0
{
267
0
  MK_PROXY(name, port, protocol, pkg_malloc, pkg_free, hostent_cpy);
268
0
}
269
270
271
struct proxy_l *mk_shm_proxy(str *name, unsigned short port, int protocol)
272
0
{
273
0
  MK_PROXY(name, port, protocol, shm_malloc, shm_free, hostent_shm_cpy);
274
0
}
275
276
277
/* same as mk_proxy, but get the host as an ip*/
278
struct proxy_l *mk_proxy_from_ip(
279
    struct ip_addr *ip, unsigned short port, int proto)
280
0
{
281
0
  struct proxy_l *p;
282
283
0
  p = (struct proxy_l *)pkg_malloc(sizeof(struct proxy_l));
284
0
  if(p == 0) {
285
0
    PKG_MEM_CRITICAL;
286
0
    goto error;
287
0
  }
288
0
  memset(p, 0, sizeof(struct proxy_l));
289
290
0
  p->port = port;
291
0
  p->proto = proto;
292
0
  p->host.h_addrtype = ip->af;
293
0
  p->host.h_length = ip->len;
294
0
  p->host.h_addr_list = pkg_malloc(2 * sizeof(char *));
295
0
  if(p->host.h_addr_list == 0) {
296
0
    PKG_MEM_ERROR;
297
0
    pkg_free(p);
298
0
    goto error;
299
0
  }
300
0
  p->host.h_addr_list[1] = 0;
301
0
  p->host.h_addr_list[0] = pkg_malloc(ip->len + 1);
302
0
  if(p->host.h_addr_list[0] == 0) {
303
0
    PKG_MEM_ERROR;
304
0
    pkg_free(p->host.h_addr_list);
305
0
    pkg_free(p);
306
0
    goto error;
307
0
  }
308
309
0
  memcpy(p->host.h_addr_list[0], ip->u.addr, ip->len);
310
0
  p->host.h_addr_list[0][ip->len] = 0;
311
312
0
  return p;
313
314
0
error:
315
0
  return 0;
316
0
}
317
318
319
void free_proxy(struct proxy_l *p)
320
0
{
321
0
  if(p)
322
0
    free_hostent(&p->host);
323
0
}
324
325
326
void free_shm_proxy(struct proxy_l *p)
327
0
{
328
0
  if(p)
329
0
    free_shm_hostent(&p->host);
330
0
}