- ipv6 support (-DUSE_IPV6)
[sip-router] / proxy.c
1 /*
2  * $Id$
3  *
4  * proxy list & assoc. functions
5  *
6  */
7
8
9 #include "proxy.h"
10 #include "error.h"
11 #include "dprint.h"
12
13 #include <string.h>
14 #include <stdlib.h>
15 #include <sys/socket.h>
16
17 #ifdef DNS_IP_HACK
18 #include "ut.h"
19 #endif
20
21 #include "resolve.h"
22 #include "ip_addr.h"
23
24 #ifdef DEBUG_DMALLOC
25 #include <dmalloc.h>
26 #endif
27
28 struct proxy_l* proxies=0;
29
30
31
32 /* searches for the proxy named 'name', on port 'port'
33    returns: pointer to proxy_l on success or 0 if not found */ 
34 static struct proxy_l* find_proxy(char *name, unsigned short port)
35 {
36         struct proxy_l* t;
37         for(t=proxies; t; t=t->next)
38                 if ((strcasecmp(t->name, name)==0) && (t->port==port))
39                         break;
40         return t;
41 }
42
43
44
45 /* copies a hostent structure*, returns 0 on success, <0 on error*/
46 static int hostent_cpy(struct hostent *dst, struct hostent* src)
47 {
48         unsigned len,len2;
49         int r,ret,i;
50
51         /* start copying the host entry.. */
52         /* copy h_name */
53         len=strlen(src->h_name)+1;
54         dst->h_name=(char*)malloc(sizeof(char) * len);
55         if (dst->h_name) strncpy(dst->h_name,src->h_name, len);
56         else{
57                 ret=E_OUT_OF_MEM;
58                 goto error;
59         }
60
61         /* copy h_aliases */
62         for (len=0;src->h_aliases[len];len++);
63         dst->h_aliases=(char**)malloc(sizeof(char*)*(len+1));
64         if (dst->h_aliases==0){
65                 ret=E_OUT_OF_MEM;
66                 free(dst->h_name);
67                 goto error;
68         }
69         memset((void*)dst->h_aliases, 0, sizeof(char*) * (len+1) );
70         for (i=0;i<len;i++){
71                 len2=strlen(src->h_aliases[i])+1;
72                 dst->h_aliases[i]=(char*)malloc(sizeof(char)*len2);
73                 if (dst->h_aliases==0){
74                         ret=E_OUT_OF_MEM;
75                         free(dst->h_name);
76                         for(r=0; r<i; r++)      free(dst->h_aliases[r]);
77                         free(dst->h_aliases);
78                         goto error;
79                 }
80                 strncpy(dst->h_aliases[i], src->h_aliases[i], len2);
81         }
82         /* copy h_addr_list */
83         for (len=0;src->h_addr_list[len];len++);
84         dst->h_addr_list=(char**)malloc(sizeof(char*)*(len+1));
85         if (dst->h_addr_list==0){
86                 ret=E_OUT_OF_MEM;
87                 free(dst->h_name);
88                 for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
89                 free(dst->h_aliases[r]);
90                 free(dst->h_aliases);
91                 goto error;
92         }
93         memset((void*)dst->h_addr_list, 0, sizeof(char*) * (len+1) );
94         for (i=0;i<len;i++){
95                 dst->h_addr_list[i]=(char*)malloc(sizeof(char)*src->h_length);
96                 if (dst->h_addr_list[i]==0){
97                         ret=E_OUT_OF_MEM;
98                         free(dst->h_name);
99                         for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
100                         free(dst->h_aliases[r]);
101                         free(dst->h_aliases);
102                         for (r=0; r<i;r++) free(dst->h_addr_list[r]);
103                         free(dst->h_addr_list);
104                         goto error;
105                 }
106                 memcpy(dst->h_addr_list[i], src->h_addr_list[i], src->h_length);
107         }
108
109         /* copy h_addr_type & length */
110         dst->h_addrtype=src->h_addrtype;
111         dst->h_length=src->h_length;
112         /*finished hostent copy */
113         
114         return 0;
115
116 error:
117         LOG(L_CRIT, "ERROR: hostent_cpy: memory allocation failure\n");
118         return ret;
119 }
120
121
122
123 void free_hostent(struct hostent *dst)
124 {
125         int r;
126         if (dst->h_name) free(dst->h_name);
127         if (dst->h_aliases){
128                 for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
129                 free(dst->h_aliases[r]);
130                 free(dst->h_aliases);
131         }
132         if (dst->h_addr_list){
133                 for (r=0; dst->h_addr_list[r];r++) free(dst->h_addr_list[r]);
134                 free(dst->h_addr_list[r]);
135                 free(dst->h_addr_list);
136         }
137 }
138
139
140
141
142 struct proxy_l* add_proxy(char* name, unsigned short port)
143 {
144         struct proxy_l* p;
145         
146         if ((p=find_proxy(name, port))!=0) return p;
147         if ((p=mk_proxy(name, port))==0) goto error;
148         /* add p to the proxy list */
149         p->next=proxies;
150         proxies=p;
151         return p;
152
153 error:
154         return 0;
155 }
156
157
158
159
160 /* same as add_proxy, but it doesn't add the proxy to the list*/
161 struct proxy_l* mk_proxy(char* name, unsigned short port)
162 {
163         struct proxy_l* p;
164         struct hostent* he;
165 #ifdef DNS_IP_HACK
166         int err;
167         unsigned int ip;
168         int len;
169 #endif
170
171         p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
172         if (p==0){
173                 LOG(L_CRIT, "ERROR: mk_proxy: memory allocation failure\n");
174                 goto error;
175         }
176         memset(p,0,sizeof(struct proxy_l));
177         p->name=name;
178         p->port=port;
179 #ifdef DNS_IP_HACK
180         /* fast ipv4 string to address conversion*/
181         len=strlen(name);
182         ip=str2ip((unsigned char*)name, len, &err);
183         if (err==0){
184                 p->host.h_name=malloc(len+1);
185                 if (p->host.h_name==0) goto error;
186                 memcpy(p->host.h_name, name, len);
187                 p->host.h_aliases=malloc(sizeof(char*));
188                 if (p->host.h_aliases==0) {
189                         free(p->host.h_name);
190                         goto error;
191                 }
192                 p->host.h_aliases[0]=0;
193                 p->host.h_addrtype=AF_INET;
194                 p->host.h_length=4;
195                 p->host.h_addr_list=malloc(2*sizeof(char*));
196                 if (p->host.h_addr_list==0){
197                         free(p->host.h_name);
198                         free(p->host.h_aliases);
199                         goto error;
200                 }
201                 p->host.h_addr_list[1]=0;
202                 p->host.h_addr_list[0]=malloc(5);
203                 if (p->host.h_addr_list[0]==0){
204                         free(p->host.h_name);
205                         free(p->host.h_aliases);
206                         free(p->host.h_addr_list);
207                         goto error;
208                 }
209                 memcpy(p->host.h_addr_list[0], (char*)&ip, 4);
210                 p->host.h_addr_list[0][4]=0;
211
212                 return p;
213         }
214 #endif
215         /* fail over to normal lookup */
216
217         he=resolvehost(name);
218         if (he==0){
219                 LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
220                                         " \"%s\"\n", name);
221                 free(p);
222                 goto error;
223         }
224         if (hostent_cpy(&(p->host), he)!=0){
225                 free(p);
226                 goto error;
227         }
228         p->ok=1;
229         return p;
230 error:
231         return 0;
232 }
233
234
235
236 /* same as mk_proxy, but get the host as an ip*/
237 struct proxy_l* mk_proxy_from_ip(struct ip_addr* ip, unsigned short port)
238 {
239         struct proxy_l* p;
240
241         p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
242         if (p==0){
243                 LOG(L_CRIT, "ERROR: mk_proxy_from_ip: memory allocation failure\n");
244                 goto error;
245         }
246         memset(p,0,sizeof(struct proxy_l));
247
248         p->port=port;
249         p->host.h_addrtype=ip->af;
250         p->host.h_length=ip->len;
251         p->host.h_addr_list=malloc(2*sizeof(char*));
252         if (p->host.h_addr_list==0) goto error;
253         p->host.h_addr_list[1]=0;
254         p->host.h_addr_list[0]=malloc(ip->len+1);
255         if (p->host.h_addr_list[0]==0){
256                 free(p->host.h_addr_list);
257                 goto error;
258         }
259
260         memcpy(p->host.h_addr_list[0], ip->u.addr, ip->len);
261         p->host.h_addr_list[0][ip->len]=0;
262
263         return p;
264
265 error:
266         return 0;
267 }
268
269
270
271
272 void free_proxy(struct proxy_l* p)
273 {
274         if (p) free_hostent(&p->host);
275 }