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