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