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