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