modules/ims_qos: added patch for flow-description bug when request originates from...
[sip-router] / proxy.c
1 /*
2  * proxy list & assoc. functions
3  *
4  *
5  * Copyright (C) 2001-2003 FhG Fokus
6  *
7  * This file is part of Kamailio, a free SIP server.
8  *
9  * Kamailio is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * Kamailio is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License 
20  * along with this program; if not, write to the Free Software 
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 /*!
25  * \file
26  * \brief Kamailio core :: proxy list & assoc. functions
27  * \ingroup core
28  * Module: \ref core
29  */
30
31
32
33 #include "config.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
56
57 /* searches for the proxy named 'name', on port 'port' with 
58    proto 'proto'; if proto==0 => proto wildcard (will match any proto)
59    returns: pointer to proxy_l on success or 0 if not found */ 
60 static struct proxy_l* find_proxy(str *name, unsigned short port, int proto)
61 {
62         struct proxy_l* t;
63         for(t=proxies; t; t=t->next)
64                 if (((t->name.len == name->len) &&
65                          ((proto==PROTO_NONE)||(t->proto==proto))&&
66                         (strncasecmp(t->name.s, name->s, name->len)==0)) &&
67                                 (t->port==port))
68                         break;
69         return t;
70 }
71
72
73 #define HOSTENT_CPY(dst, src, he_malloc, he_free)                                               \
74         do {                                                                                                                            \
75                 unsigned len,len2;                                                                                              \
76                 int r,i;                                                                                                                \
77                                                                                                                                                 \
78                 /* start copying the host entry.. */                                                    \
79                 /* copy h_name */                                                                                               \
80                 len=strlen(src->h_name)+1;                                                                              \
81                 dst->h_name=(char*)he_malloc(sizeof(char) * len);                               \
82                 if (dst->h_name) strncpy(dst->h_name,src->h_name, len);                 \
83                 else{                                                                                                                   \
84                         ser_error=ret=E_OUT_OF_MEM;                                                                     \
85                         goto error;                                                                                                     \
86                 }                                                                                                                               \
87                                                                                                                                                 \
88                 /* copy h_aliases */                                                                                    \
89                 len=0;                                                                                                                  \
90                 if (src->h_aliases)                                                                                             \
91                         for (;src->h_aliases[len];len++);                                                       \
92                 dst->h_aliases=(char**)he_malloc(sizeof(char*)*(len+1));                \
93                 if (dst->h_aliases==0){                                                                                 \
94                         ser_error=ret=E_OUT_OF_MEM;                                                                     \
95                         he_free(dst->h_name);                                                                           \
96                         goto error;                                                                                                     \
97                 }                                                                                                                               \
98                 memset((void*)dst->h_aliases, 0, sizeof(char*) * (len+1) );             \
99                 for (i=0;i<len;i++){                                                                                    \
100                         len2=strlen(src->h_aliases[i])+1;                                                       \
101                         dst->h_aliases[i]=(char*)he_malloc(sizeof(char)*len2);          \
102                         if (dst->h_aliases==0){                                                                         \
103                                 ser_error=ret=E_OUT_OF_MEM;                                                             \
104                                 he_free(dst->h_name);                                                                   \
105                                 for(r=0; r<i; r++)      he_free(dst->h_aliases[r]);                     \
106                                 he_free(dst->h_aliases);                                                                \
107                                 goto error;                                                                                             \
108                         }                                                                                                                       \
109                         strncpy(dst->h_aliases[i], src->h_aliases[i], len2);            \
110                 }                                                                                                                               \
111                 /* copy h_addr_list */                                                                                  \
112                 len=0;                                                                                                                  \
113                 if (src->h_addr_list)                                                                                   \
114                         for (;src->h_addr_list[len];len++);                                                     \
115                 dst->h_addr_list=(char**)he_malloc(sizeof(char*)*(len+1));              \
116                 if (dst->h_addr_list==0){                                                                               \
117                         ser_error=ret=E_OUT_OF_MEM;                                                                     \
118                         he_free(dst->h_name);                                                                           \
119                         for(r=0; dst->h_aliases[r]; r++)                                                        \
120                                 he_free(dst->h_aliases[r]);                                                             \
121                         he_free(dst->h_aliases[r]);                                                                     \
122                         he_free(dst->h_aliases);                                                                        \
123                         goto error;                                                                                                     \
124                 }                                                                                                                               \
125                 memset((void*)dst->h_addr_list, 0, sizeof(char*) * (len+1) );   \
126                 for (i=0;i<len;i++){                                                                                    \
127                         dst->h_addr_list[i]=                                                                            \
128                                 (char*)he_malloc(sizeof(char)*src->h_length);                   \
129                         if (dst->h_addr_list[i]==0){                                                            \
130                                 ser_error=ret=E_OUT_OF_MEM;                                                             \
131                                 he_free(dst->h_name);                                                                   \
132                                 for(r=0; dst->h_aliases[r]; r++)                                                \
133                                         he_free(dst->h_aliases[r]);                                                     \
134                                 he_free(dst->h_aliases[r]);                                                             \
135                                 he_free(dst->h_aliases);                                                                \
136                                 for (r=0; r<i;r++) he_free(dst->h_addr_list[r]);                \
137                                 he_free(dst->h_addr_list);                                                              \
138                                 goto error;                                                                                             \
139                         }                                                                                                                       \
140                         memcpy(dst->h_addr_list[i], src->h_addr_list[i],                        \
141                                    src->h_length);                                                                              \
142                 }                                                                                                                               \
143                                                                                                                                                 \
144                 /* copy h_addr_type & length */                                                                 \
145                 dst->h_addrtype=src->h_addrtype;                                                                \
146                 dst->h_length=src->h_length;                                                                    \
147                 /*finished hostent copy */                                                                              \
148                                                                                                                                                 \
149                 return 0;                                                                                                               \
150         } while(0)
151
152
153 #define FREE_HOSTENT(dst, he_free)                                              \
154         do {                                                                                            \
155                 int r;                                                                                  \
156                 if (dst->h_name) he_free(dst->h_name);                  \
157                 if (dst->h_aliases){                                                    \
158                         for(r=0; dst->h_aliases[r]; r++) {                      \
159                                 he_free(dst->h_aliases[r]);                             \
160                         }                                                                                       \
161                         he_free(dst->h_aliases);                                        \
162                 }                                                                                               \
163                 if (dst->h_addr_list){                                                  \
164                         for (r=0; dst->h_addr_list[r];r++) {            \
165                                 he_free(dst->h_addr_list[r]);                   \
166                         }                                                                                       \
167                         he_free(dst->h_addr_list);                                      \
168                 }                                                                                               \
169         } while(0)
170
171
172
173 /* copies a hostent structure*, returns 0 on success, <0 on error*/
174 static int hostent_cpy(struct hostent *dst, struct hostent* src)
175 {
176         int ret;
177         HOSTENT_CPY(dst, src, pkg_malloc, pkg_free);
178 error:
179         LM_CRIT("memory allocation failure\n");
180         return ret;
181 }
182
183
184 static int hostent_shm_cpy(struct hostent *dst, struct hostent* src)
185 {
186         int ret;
187         HOSTENT_CPY(dst, src, shm_malloc, shm_free);
188 error:
189         LM_CRIT("memory allocation failure\n");
190         return ret;
191 }
192
193
194 void free_hostent(struct hostent* dst)
195 {
196         FREE_HOSTENT(dst, pkg_free);
197 }
198
199 void free_shm_hostent(struct hostent* dst)
200 {
201         FREE_HOSTENT(dst, shm_free);
202 }
203
204
205
206 struct proxy_l* add_proxy(str* name, unsigned short port, int proto)
207 {
208         struct proxy_l* p;
209         
210         if ((p=find_proxy(name, port, proto))!=0) return p;
211         if ((p=mk_proxy(name, port, proto))==0) goto error;
212         /* add p to the proxy list */
213         p->next=proxies;
214         proxies=p;
215         return p;
216
217 error:
218         return 0;
219 }
220
221
222 #define MK_PROXY(name, port, protocol, p_malloc, p_free, he_cpy)                \
223         do {                                                                                                                            \
224                 struct proxy_l* p;                                                                                              \
225                 struct hostent* he;                                                                                             \
226                 char proto;                                                                                                             \
227                                                                                                                                                 \
228                 p=(struct proxy_l*) p_malloc(sizeof(struct proxy_l));                   \
229                 if (p==0){                                                                                                              \
230                         ser_error=E_OUT_OF_MEM;                                                                         \
231                         LM_ERR("memory allocation failure\n");                                          \
232                         goto error;                                                                                                     \
233                 }                                                                                                                               \
234                 memset(p,0,sizeof(struct proxy_l));                                                             \
235                 p->name=*name;                                                                                                  \
236                 p->port=port;                                                                                                   \
237                                                                                                                                                 \
238                 LM_DBG("doing DNS lookup...\n");                                                                \
239                 proto=protocol;                                                                                                 \
240                 he=sip_resolvehost(name, &(p->port), &proto);                                   \
241                 if (he==0){                                                                                                             \
242                         ser_error=E_BAD_ADDRESS;                                                                        \
243                         LM_CRIT("could not resolve hostname:"                                           \
244                                 " \"%.*s\"\n", name->len, name->s);                                             \
245                         p_free(p);                                                                                                      \
246                         goto error;                                                                                                     \
247                 }                                                                                                                               \
248                 if (he_cpy(&(p->host), he)!=0){                                                                 \
249                         p_free(p);                                                                                                      \
250                         goto error;                                                                                                     \
251                 }                                                                                                                               \
252                 p->proto=proto;                                                                                                 \
253                 p->ok=1;                                                                                                                \
254                 return p;                                                                                                               \
255         error:                                                                                                                          \
256                 return 0;                                                                                                               \
257                                                                                                                                                 \
258         } while(0)
259
260 /* same as add_proxy, but it doesn't add the proxy to the list
261  * uses also SRV if possible & port==0 (quick hack) */
262
263 struct proxy_l* mk_proxy(str* name, unsigned short port, int protocol)
264 {
265         MK_PROXY(name, port, protocol, pkg_malloc, pkg_free, hostent_cpy);
266 }
267
268
269 struct proxy_l* mk_shm_proxy(str* name, unsigned short port, int protocol)
270 {
271         MK_PROXY(name, port, protocol, shm_malloc, shm_free, hostent_shm_cpy);
272 }
273
274
275
276 /* same as mk_proxy, but get the host as an ip*/
277 struct proxy_l* mk_proxy_from_ip(struct ip_addr* ip, unsigned short port,
278                                                                         int proto)
279 {
280         struct proxy_l* p;
281
282         p=(struct proxy_l*) pkg_malloc(sizeof(struct proxy_l));
283         if (p==0){
284                 LM_CRIT("memory allocation failure\n");
285                 goto error;
286         }
287         memset(p,0,sizeof(struct proxy_l));
288
289         p->port=port;
290         p->proto=proto;
291         p->host.h_addrtype=ip->af;
292         p->host.h_length=ip->len;
293         p->host.h_addr_list=pkg_malloc(2*sizeof(char*));
294         if (p->host.h_addr_list==0) goto error;
295         p->host.h_addr_list[1]=0;
296         p->host.h_addr_list[0]=pkg_malloc(ip->len+1);
297         if (p->host.h_addr_list[0]==0){
298                 pkg_free(p->host.h_addr_list);
299                 goto error;
300         }
301
302         memcpy(p->host.h_addr_list[0], ip->u.addr, ip->len);
303         p->host.h_addr_list[0][ip->len]=0;
304
305         return p;
306
307 error:
308         return 0;
309 }
310
311
312
313
314 void free_proxy(struct proxy_l* p)
315 {
316         if (p) free_hostent(&p->host);
317 }
318
319
320 void free_shm_proxy(struct proxy_l* p)
321 {
322         if (p) free_shm_hostent(&p->host);
323 }