/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 | } |