GPLization banner introduced to *.[hc] files
[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
32
33 #include "config.h"
34 #include "proxy.h"
35 #include "error.h"
36 #include "dprint.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 #ifdef DEBUG_DMALLOC
51 #include <dmalloc.h>
52 #endif
53
54 struct proxy_l* proxies=0;
55
56
57
58 /* searches for the proxy named 'name', on port 'port'
59    returns: pointer to proxy_l on success or 0 if not found */ 
60 static struct proxy_l* find_proxy(char *name, unsigned short port)
61 {
62         struct proxy_l* t;
63         for(t=proxies; t; t=t->next)
64                 if ((strcasecmp(t->name, name)==0) && (t->port==port))
65                         break;
66         return t;
67 }
68
69
70
71 /* copies a hostent structure*, returns 0 on success, <0 on error*/
72 static int hostent_cpy(struct hostent *dst, struct hostent* src)
73 {
74         unsigned len,len2;
75         int r,ret,i;
76
77         /* start copying the host entry.. */
78         /* copy h_name */
79         len=strlen(src->h_name)+1;
80         dst->h_name=(char*)malloc(sizeof(char) * len);
81         if (dst->h_name) strncpy(dst->h_name,src->h_name, len);
82         else{
83                 ser_error=ret=E_OUT_OF_MEM;
84                 goto error;
85         }
86
87         /* copy h_aliases */
88         for (len=0;src->h_aliases[len];len++);
89         dst->h_aliases=(char**)malloc(sizeof(char*)*(len+1));
90         if (dst->h_aliases==0){
91                 ser_error=ret=E_OUT_OF_MEM;
92                 free(dst->h_name);
93                 goto error;
94         }
95         memset((void*)dst->h_aliases, 0, sizeof(char*) * (len+1) );
96         for (i=0;i<len;i++){
97                 len2=strlen(src->h_aliases[i])+1;
98                 dst->h_aliases[i]=(char*)malloc(sizeof(char)*len2);
99                 if (dst->h_aliases==0){
100                         ser_error=ret=E_OUT_OF_MEM;
101                         free(dst->h_name);
102                         for(r=0; r<i; r++)      free(dst->h_aliases[r]);
103                         free(dst->h_aliases);
104                         goto error;
105                 }
106                 strncpy(dst->h_aliases[i], src->h_aliases[i], len2);
107         }
108         /* copy h_addr_list */
109         for (len=0;src->h_addr_list[len];len++);
110         dst->h_addr_list=(char**)malloc(sizeof(char*)*(len+1));
111         if (dst->h_addr_list==0){
112                 ser_error=ret=E_OUT_OF_MEM;
113                 free(dst->h_name);
114                 for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
115                 free(dst->h_aliases[r]);
116                 free(dst->h_aliases);
117                 goto error;
118         }
119         memset((void*)dst->h_addr_list, 0, sizeof(char*) * (len+1) );
120         for (i=0;i<len;i++){
121                 dst->h_addr_list[i]=(char*)malloc(sizeof(char)*src->h_length);
122                 if (dst->h_addr_list[i]==0){
123                         ser_error=ret=E_OUT_OF_MEM;
124                         free(dst->h_name);
125                         for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
126                         free(dst->h_aliases[r]);
127                         free(dst->h_aliases);
128                         for (r=0; r<i;r++) free(dst->h_addr_list[r]);
129                         free(dst->h_addr_list);
130                         goto error;
131                 }
132                 memcpy(dst->h_addr_list[i], src->h_addr_list[i], src->h_length);
133         }
134
135         /* copy h_addr_type & length */
136         dst->h_addrtype=src->h_addrtype;
137         dst->h_length=src->h_length;
138         /*finished hostent copy */
139         
140         return 0;
141
142 error:
143         LOG(L_CRIT, "ERROR: hostent_cpy: memory allocation failure\n");
144         return ret;
145 }
146
147
148
149 void free_hostent(struct hostent *dst)
150 {
151         int r;
152         if (dst->h_name) free(dst->h_name);
153         if (dst->h_aliases){
154                 for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
155                 free(dst->h_aliases[r]);
156                 free(dst->h_aliases);
157         }
158         if (dst->h_addr_list){
159                 for (r=0; dst->h_addr_list[r];r++) free(dst->h_addr_list[r]);
160                 free(dst->h_addr_list[r]);
161                 free(dst->h_addr_list);
162         }
163 }
164
165
166
167
168 struct proxy_l* add_proxy(char* name, unsigned short port)
169 {
170         struct proxy_l* p;
171         
172         if ((p=find_proxy(name, port))!=0) return p;
173         if ((p=mk_proxy(name, port))==0) goto error;
174         /* add p to the proxy list */
175         p->next=proxies;
176         proxies=p;
177         return p;
178
179 error:
180         return 0;
181 }
182
183
184
185
186 /* same as add_proxy, but it doesn't add the proxy to the list
187  * uses also SRV if possible (quick hack) */
188
189 struct proxy_l* mk_proxy(char* name, unsigned short port)
190 {
191         struct proxy_l* p;
192         struct hostent* he;
193
194         p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
195         if (p==0){
196                 ser_error=E_OUT_OF_MEM;
197                 LOG(L_CRIT, "ERROR: mk_proxy: memory allocation failure\n");
198                 goto error;
199         }
200         memset(p,0,sizeof(struct proxy_l));
201         p->name=name;
202         p->port=port;
203
204         DBG("DEBUG: mk_proxy: doing DNS lookup...\n");
205         he=sip_resolvehost(name, &(p->port));
206         if (he==0){
207                 ser_error=E_BAD_ADDRESS;
208                 LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
209                                         " \"%s\"\n", name);
210                 free(p);
211                 goto error;
212         }
213         if (hostent_cpy(&(p->host), he)!=0){
214                 free(p);
215                 goto error;
216         }
217         p->ok=1;
218         return p;
219 error:
220         return 0;
221 }
222
223
224
225 /* same as mk_proxy, but get the host as an ip*/
226 struct proxy_l* mk_proxy_from_ip(struct ip_addr* ip, unsigned short port)
227 {
228         struct proxy_l* p;
229
230         p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
231         if (p==0){
232                 LOG(L_CRIT, "ERROR: mk_proxy_from_ip: memory allocation failure\n");
233                 goto error;
234         }
235         memset(p,0,sizeof(struct proxy_l));
236
237         p->port=port;
238         p->host.h_addrtype=ip->af;
239         p->host.h_length=ip->len;
240         p->host.h_addr_list=malloc(2*sizeof(char*));
241         if (p->host.h_addr_list==0) goto error;
242         p->host.h_addr_list[1]=0;
243         p->host.h_addr_list[0]=malloc(ip->len+1);
244         if (p->host.h_addr_list[0]==0){
245                 free(p->host.h_addr_list);
246                 goto error;
247         }
248
249         memcpy(p->host.h_addr_list[0], ip->u.addr, ip->len);
250         p->host.h_addr_list[0][ip->len]=0;
251
252         return p;
253
254 error:
255         return 0;
256 }
257
258
259
260
261 void free_proxy(struct proxy_l* p)
262 {
263         if (p) free_hostent(&p->host);
264 }