Coverage Report

Created: 2025-07-18 06:32

/src/opensips/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 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
 * History:
23
 * -------
24
 *  2003-02-13  all *proxy functions are now proto aware (andrei)
25
 *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
26
 *  2007-01-25  support for DNS failover added into proxy structure;
27
 *              new shm functions for copy/free added (bogdan)
28
 */
29
30
31
32
#include "config.h"
33
#include "globals.h"
34
#include "proxy.h"
35
#include "error.h"
36
#include "dprint.h"
37
#include "mem/mem.h"
38
#include "mem/shm_mem.h"
39
40
#include <string.h>
41
#include <stdlib.h>
42
#include <sys/socket.h>
43
44
#ifdef DNS_IP_HACK
45
#include "ut.h"
46
#endif
47
48
#include "resolve.h"
49
#include "ip_addr.h"
50
#include "globals.h"
51
52
53
struct proxy_l* proxies=0;
54
55
int disable_dns_failover=0;
56
57
58
int hostent_shm_cpy(struct hostent *dst, struct hostent* src)
59
0
{
60
0
  int  i;
61
0
  char *p;
62
63
0
  for( i=0 ; src->h_addr_list[i] ; i++ );
64
65
0
  dst->h_addr_list = (char**)shm_malloc
66
0
    (i * (src->h_length + sizeof(char*)) + sizeof(char*));
67
0
  if (dst->h_addr_list==NULL)
68
0
    return -1;
69
70
0
  p = ((char*)dst->h_addr_list) + (i+1)*sizeof(char*);
71
0
  dst->h_addr_list[i] = 0;
72
73
0
  for( i-- ; i>=0 ; i-- ) {
74
0
    dst->h_addr_list[i] = p;
75
0
    memcpy( dst->h_addr_list[i], src->h_addr_list[i], src->h_length );
76
0
    p += src->h_length;
77
0
  }
78
79
0
  dst->h_addr = dst->h_addr_list[0];
80
0
  dst->h_addrtype = src->h_addrtype;
81
0
  dst->h_length = src->h_length;
82
0
  return 0;
83
0
}
84
85
86
void free_shm_hostent(struct hostent *dst)
87
0
{
88
0
  if (dst->h_addr_list)
89
0
    shm_free(dst->h_addr_list);
90
0
}
91
92
93
/* copies a hostent structure*, returns 0 on success, <0 on error*/
94
int hostent_cpy(struct hostent *dst, struct hostent* src)
95
0
{
96
0
  unsigned int len,len2, i, r;
97
0
  int ret;
98
99
  /* start copying the host entry.. */
100
  /* copy h_name */
101
0
  len=strlen(src->h_name)+1;
102
0
  dst->h_name=(char*)pkg_malloc(sizeof(char) * len);
103
0
  if (dst->h_name) strncpy(dst->h_name,src->h_name, len);
104
0
  else{
105
0
    ser_error=ret=E_OUT_OF_MEM;
106
0
    goto error;
107
0
  }
108
109
  /* copy h_aliases */
110
0
  len=0;
111
0
  if (src->h_aliases)
112
0
    for (;src->h_aliases[len];len++);
113
0
  dst->h_aliases=(char**)pkg_malloc(sizeof(char*)*(len+1));
114
0
  if (dst->h_aliases==0){
115
0
    ser_error=ret=E_OUT_OF_MEM;
116
0
    pkg_free(dst->h_name);
117
0
    goto error;
118
0
  }
119
0
  memset((void*)dst->h_aliases, 0, sizeof(char*) * (len+1) );
120
0
  for (i=0;i<len;i++){
121
0
    len2=strlen(src->h_aliases[i])+1;
122
0
    dst->h_aliases[i]=(char*)pkg_malloc(sizeof(char)*len2);
123
0
    if (dst->h_aliases[i]==0){
124
0
      ser_error=ret=E_OUT_OF_MEM;
125
0
      pkg_free(dst->h_name);
126
0
      for(r=0; r<i; r++) pkg_free(dst->h_aliases[r]);
127
0
      pkg_free(dst->h_aliases);
128
0
      goto error;
129
0
    }
130
0
    strncpy(dst->h_aliases[i], src->h_aliases[i], len2);
131
0
  }
132
  /* copy h_addr_list */
133
0
  len=0;
134
0
  if (src->h_addr_list)
135
0
    for (;src->h_addr_list[len];len++);
136
0
  dst->h_addr_list=(char**)pkg_malloc(sizeof(char*)*(len+1));
137
0
  if (dst->h_addr_list==0){
138
0
    ser_error=ret=E_OUT_OF_MEM;
139
0
    pkg_free(dst->h_name);
140
0
    for(r=0; dst->h_aliases[r]; r++) pkg_free(dst->h_aliases[r]);
141
0
    pkg_free(dst->h_aliases);
142
0
    goto error;
143
0
  }
144
0
  memset((void*)dst->h_addr_list, 0, sizeof(char*) * (len+1) );
145
0
  for (i=0;i<len;i++){
146
0
    dst->h_addr_list[i]=(char*)pkg_malloc(sizeof(char)*src->h_length);
147
0
    if (dst->h_addr_list[i]==0){
148
0
      ser_error=ret=E_OUT_OF_MEM;
149
0
      pkg_free(dst->h_name);
150
0
      for(r=0; dst->h_aliases[r]; r++) pkg_free(dst->h_aliases[r]);
151
0
      pkg_free(dst->h_aliases);
152
0
      for (r=0; r<i;r++) pkg_free(dst->h_addr_list[r]);
153
0
      pkg_free(dst->h_addr_list);
154
0
      goto error;
155
0
    }
156
0
    memcpy(dst->h_addr_list[i], src->h_addr_list[i], src->h_length);
157
0
  }
158
159
  /* copy h_addr_type & length */
160
0
  dst->h_addrtype=src->h_addrtype;
161
0
  dst->h_length=src->h_length;
162
  /*finished hostent copy */
163
164
0
  return 0;
165
166
0
error:
167
0
  LM_CRIT("pkg memory allocation failure\n");
168
0
  return ret;
169
0
}
170
171
172
173
void free_hostent(struct hostent *dst)
174
0
{
175
0
  int r;
176
0
  if (dst->h_name) pkg_free(dst->h_name);
177
0
  if (dst->h_aliases){
178
0
    for(r=0; dst->h_aliases[r]; r++) {
179
0
      pkg_free(dst->h_aliases[r]);
180
0
    }
181
0
    pkg_free(dst->h_aliases);
182
0
  }
183
0
  if (dst->h_addr_list){
184
0
    for (r=0; dst->h_addr_list[r];r++) {
185
0
      pkg_free(dst->h_addr_list[r]);
186
0
    }
187
0
    pkg_free(dst->h_addr_list);
188
0
  }
189
0
}
190
191
192
193
/* Creates a proxy structure out of the host, port and proto
194
 * uses also SRV if possible & port==0 (quick hack) */
195
196
struct proxy_l* mk_proxy(str* name, unsigned short port, unsigned short proto,
197
    int is_sips)
198
0
{
199
0
  struct proxy_l* p;
200
0
  struct hostent* he;
201
202
0
  p=(struct proxy_l*) pkg_malloc(sizeof(struct proxy_l));
203
0
  if (p==0){
204
0
    ser_error=E_OUT_OF_MEM;
205
0
    LM_CRIT("pkg memory allocation failure\n");
206
0
    goto error;
207
0
  }
208
0
  memset(p,0,sizeof(struct proxy_l));
209
0
  p->name=*name;
210
0
  p->port=port;
211
0
  p->proto=proto;
212
213
0
  LM_DBG("doing DNS lookup...\n");
214
0
  he = sip_resolvehost(name, &(p->port), &p->proto, is_sips,
215
0
    disable_dns_failover?0:&p->dn );
216
0
  if (!he || !he->h_addr_list[0]) {
217
0
    ser_error=E_BAD_ADDRESS;
218
0
    LM_CRIT("could not resolve hostname: \"%.*s\"%s\n",
219
0
            name->len, name->s, he ? " (0 results)" : "");
220
0
    pkg_free(p);
221
0
    goto error;
222
0
  }
223
0
  if (hostent_cpy(&(p->host), he)!=0){
224
0
    free_dns_res( p );
225
0
    pkg_free(p);
226
0
    goto error;
227
0
  }
228
0
  return p;
229
0
error:
230
0
  return 0;
231
0
}
232
233
234
235
/* same as mk_proxy, but in shared memory
236
 * uses also SRV if possible & port==0 (quick hack) */
237
struct proxy_l* mk_proxy_from_ip(struct ip_addr* ip, unsigned short port,
238
    unsigned short proto)
239
0
{
240
0
  struct proxy_l* p;
241
242
0
  p=(struct proxy_l*) pkg_malloc(sizeof(struct proxy_l));
243
0
  if (p==0){
244
0
    LM_CRIT("pkg memory allocation failure\n");
245
0
    goto error;
246
0
  }
247
0
  memset(p,0,sizeof(struct proxy_l));
248
249
0
  p->port=port;
250
0
  p->proto=proto;
251
0
  p->host.h_addrtype=ip->af;
252
0
  p->host.h_length=ip->len;
253
0
  p->host.h_addr_list=pkg_malloc(2*sizeof(char*));
254
0
  if (p->host.h_addr_list==0) goto error;
255
0
  p->host.h_addr_list[1]=0;
256
0
  p->host.h_addr_list[0]=pkg_malloc(ip->len+1);
257
0
  if (p->host.h_addr_list[0]==0){
258
0
    pkg_free(p->host.h_addr_list);
259
0
    goto error;
260
0
  }
261
262
0
  memcpy(p->host.h_addr_list[0], ip->u.addr, ip->len);
263
0
  p->host.h_addr_list[0][ip->len]=0;
264
265
0
  return p;
266
267
0
error:
268
0
  return 0;
269
0
}
270
271
272
273
void free_proxy(struct proxy_l* p)
274
0
{
275
0
  if (p) {
276
0
    free_hostent(&p->host);
277
0
    free_dns_res( p );
278
0
  }
279
0
}
280
281
282
void free_shm_proxy(struct proxy_l* p)
283
0
{
284
0
  if (p) {
285
0
    free_shm_hostent(&p->host);
286
0
    free_dns_res(p);
287
0
  }
288
0
}
289
290
/* same as add_proxy, but it doesn't add the proxy to the list
291
 * uses also SRV if possible & port==0 (quick hack)
292
   works in shared memory */
293
struct proxy_l* mk_shm_proxy(str* name, unsigned short port, unsigned short proto,
294
    int is_sips)
295
0
{
296
0
  struct proxy_l* p;
297
0
  struct hostent* he;
298
299
0
  p=(struct proxy_l*) shm_malloc(sizeof(struct proxy_l));
300
0
  if (p==0){
301
0
    ser_error=E_OUT_OF_MEM;
302
0
    LM_CRIT("shm memory allocation failure\n");
303
0
    goto error;
304
0
  }
305
0
  memset(p,0,sizeof(struct proxy_l));
306
0
  p->name=*name;
307
0
  p->port=port;
308
0
  p->proto=proto;
309
310
0
  LM_DBG("doing DNS lookup...\n");
311
0
  he = sip_resolvehost(name, &(p->port), &p->proto, is_sips,
312
0
    disable_dns_failover?0:&p->dn );
313
0
  if (he==0){
314
0
    ser_error=E_BAD_ADDRESS;
315
0
    LM_CRIT("could not resolve hostname: \"%.*s\"\n", name->len, name->s);
316
0
    shm_free(p);
317
0
    goto error;
318
0
  }
319
0
  if (hostent_shm_cpy(&(p->host), he)!=0){
320
0
    free_dns_res( p );
321
0
    shm_free(p);
322
0
    goto error;
323
0
  }
324
0
  return p;
325
0
error:
326
0
  return 0;
327
0
}
328
329
/* clones a proxy into pkg memory */
330
struct proxy_l* clone_proxy(struct proxy_l *sp)
331
0
{
332
0
  struct proxy_l *dp;
333
334
0
  dp = (struct proxy_l*)pkg_malloc(sizeof(struct proxy_l));
335
0
  if (dp==NULL) {
336
0
    LM_ERR("no more pkg memory\n");
337
0
    return 0;
338
0
  }
339
0
  memset( dp , 0 , sizeof(struct proxy_l));
340
341
0
  dp->port = sp->port;
342
0
  dp->proto = sp->proto;
343
0
  dp->addr_idx = sp->addr_idx;
344
345
  /* clone the hostent */
346
0
  if (hostent_cpy( &dp->host, &sp->host)!=0)
347
0
    goto error0;
348
349
  /* clone the dns resolver */
350
0
  if (sp->dn) {
351
0
    dp->dn = dns_res_copy(sp->dn);
352
0
    if (dp->dn==NULL)
353
0
      goto error1;
354
0
  }
355
356
0
  return dp;
357
0
error1:
358
0
  free_hostent(&dp->host);
359
0
error0:
360
0
  pkg_free(dp);
361
0
  return 0;
362
0
}
363
364