... | ... |
@@ -232,12 +232,6 @@ int update_sock_struct_from_via( union sockaddr_union* to, |
232 | 232 |
unsigned short port; |
233 | 233 |
|
234 | 234 |
|
235 |
-#ifdef DNS_IP_HACK |
|
236 |
- int err; |
|
237 |
- unsigned int ip; |
|
238 |
-#endif |
|
239 |
- |
|
240 |
- |
|
241 | 235 |
if (via->received){ |
242 | 236 |
DBG("update_sock_struct_from_via: using 'received'\n"); |
243 | 237 |
name=&(via->received->value); |
... | ... |
@@ -249,48 +243,37 @@ int update_sock_struct_from_via( union sockaddr_union* to, |
249 | 243 |
name=&(via->host); |
250 | 244 |
port=via->port; |
251 | 245 |
} |
252 |
-#ifdef DNS_IP_HACK |
|
253 |
- ip=str2ip((unsigned char*)name->s, name->len,&err); |
|
254 |
- if (err==0){ |
|
255 |
- to->sin.sin_family=AF_INET; |
|
256 |
- to->sin.sin_port=(via->port)?htons(via->port): htons(SIP_PORT); |
|
257 |
- memcpy(&to->sin.sin_addr, (char*)&ip, 4); |
|
258 |
- }else |
|
259 |
-#endif |
|
260 |
- { |
|
261 |
- /* we do now a malloc/memcpy because gethostbyname loves \0-terminated |
|
262 |
- strings; -jiri |
|
263 |
- but only if host is not null terminated |
|
264 |
- (host.s[len] will always be ok for a via) |
|
265 |
- BTW: when is via->host.s non null terminated? tm copy? |
|
266 |
- - andrei |
|
267 |
- Yes -- it happened on generating a 408 by TM; -jiri |
|
268 |
- */ |
|
269 |
- if (name->s[name->len]){ |
|
270 |
- host_copy=pkg_malloc( name->len+1 ); |
|
271 |
- if (!host_copy) { |
|
272 |
- LOG(L_NOTICE, "ERROR: update_sock_struct_from_via:" |
|
273 |
- " not enough memory\n"); |
|
274 |
- return -1; |
|
275 |
- } |
|
276 |
- memcpy(host_copy, name->s, name->len ); |
|
277 |
- host_copy[name->len]=0; |
|
278 |
- DBG("update_sock_struct_from_via: trying SRV lookup\n"); |
|
279 |
- he=sip_resolvehost(host_copy, &port); |
|
280 |
- |
|
281 |
- pkg_free( host_copy ); |
|
282 |
- }else{ |
|
283 |
- DBG("update_sock_struct_from_via: trying SRV lookup\n"); |
|
284 |
- he=sip_resolvehost(name->s, &port); |
|
285 |
- } |
|
286 |
- |
|
287 |
- if (he==0){ |
|
288 |
- LOG(L_NOTICE, "ERROR:forward_reply:resolve_host(%s) failure\n", |
|
289 |
- name->s); |
|
246 |
+ /* we do now a malloc/memcpy because gethostbyname loves \0-terminated |
|
247 |
+ strings; -jiri |
|
248 |
+ but only if host is not null terminated |
|
249 |
+ (host.s[len] will always be ok for a via) |
|
250 |
+ BTW: when is via->host.s non null terminated? tm copy? - andrei |
|
251 |
+ Yes -- it happened on generating a 408 by TM; -jiri |
|
252 |
+ */ |
|
253 |
+ if (name->s[name->len]){ |
|
254 |
+ host_copy=pkg_malloc( name->len+1 ); |
|
255 |
+ if (!host_copy) { |
|
256 |
+ LOG(L_NOTICE, "ERROR: update_sock_struct_from_via:" |
|
257 |
+ " not enough memory\n"); |
|
290 | 258 |
return -1; |
291 | 259 |
} |
292 |
- hostent2su(to, he, 0, htons(port)); |
|
260 |
+ memcpy(host_copy, name->s, name->len ); |
|
261 |
+ host_copy[name->len]=0; |
|
262 |
+ DBG("update_sock_struct_from_via: trying SRV lookup\n"); |
|
263 |
+ he=sip_resolvehost(host_copy, &port); |
|
264 |
+ |
|
265 |
+ pkg_free( host_copy ); |
|
266 |
+ }else{ |
|
267 |
+ DBG("update_sock_struct_from_via: trying SRV lookup\n"); |
|
268 |
+ he=sip_resolvehost(name->s, &port); |
|
269 |
+ } |
|
270 |
+ |
|
271 |
+ if (he==0){ |
|
272 |
+ LOG(L_NOTICE, "ERROR:forward_reply:resolve_host(%s) failure\n", |
|
273 |
+ name->s); |
|
274 |
+ return -1; |
|
293 | 275 |
} |
276 |
+ hostent2su(to, he, 0, htons(port)); |
|
294 | 277 |
return 1; |
295 | 278 |
} |
296 | 279 |
|
... | ... |
@@ -341,6 +341,29 @@ static inline char* ip_addr2a(struct ip_addr* ip) |
341 | 341 |
|
342 | 342 |
|
343 | 343 |
|
344 |
- |
|
345 |
- |
|
344 |
+/* converts an ip_addr structure to a hostent, returns pointer to internal |
|
345 |
+ * statical structure */ |
|
346 |
+static inline struct hostent* ip_addr2he(char* name, int len, |
|
347 |
+ struct ip_addr* ip) |
|
348 |
+{ |
|
349 |
+ static struct hostent he; |
|
350 |
+ static char hostname[256]; |
|
351 |
+ static char* p_aliases[1]; |
|
352 |
+ static char* p_addr[2]; |
|
353 |
+ static char address[16]; |
|
354 |
+ |
|
355 |
+ p_aliases[0]=0; /* no aliases*/ |
|
356 |
+ p_addr[1]=0; /* only one address*/ |
|
357 |
+ p_addr[0]=address; |
|
358 |
+ strncpy(hostname, name, (len<256)?len:256); |
|
359 |
+ if (ip->len>16) return 0; |
|
360 |
+ memcpy(address, ip->u.addr, ip->len); |
|
361 |
+ |
|
362 |
+ he.h_addrtype=ip->af; |
|
363 |
+ he.h_length=ip->len; |
|
364 |
+ he.h_addr_list=p_addr; |
|
365 |
+ he.h_aliases=p_aliases; |
|
366 |
+ he.h_name=hostname; |
|
367 |
+ return &he; |
|
368 |
+} |
|
346 | 369 |
#endif |
... | ... |
@@ -166,11 +166,6 @@ struct proxy_l* mk_proxy(char* name, unsigned short port) |
166 | 166 |
{ |
167 | 167 |
struct proxy_l* p; |
168 | 168 |
struct hostent* he; |
169 |
-#ifdef DNS_IP_HACK |
|
170 |
- int len; |
|
171 |
- int err; |
|
172 |
- unsigned int ip; |
|
173 |
-#endif |
|
174 | 169 |
|
175 | 170 |
p=(struct proxy_l*) malloc(sizeof(struct proxy_l)); |
176 | 171 |
if (p==0){ |
... | ... |
@@ -181,47 +176,6 @@ struct proxy_l* mk_proxy(char* name, unsigned short port) |
181 | 176 |
memset(p,0,sizeof(struct proxy_l)); |
182 | 177 |
p->name=name; |
183 | 178 |
p->port=port; |
184 |
-#ifdef DNS_IP_HACK |
|
185 |
- /* fast ipv4 string to address conversion*/ |
|
186 |
- len=strlen(name); |
|
187 |
- ip=str2ip((unsigned char*)name, len, &err); |
|
188 |
- if (err==0){ |
|
189 |
- p->host.h_name=malloc(len+1); |
|
190 |
- if (p->host.h_name==0) goto error; |
|
191 |
- memcpy(p->host.h_name, name, len); |
|
192 |
- p->host.h_aliases=malloc(sizeof(char*)); |
|
193 |
- if (p->host.h_aliases==0) { |
|
194 |
- ser_error=E_OUT_OF_MEM; |
|
195 |
- free(p->host.h_name); |
|
196 |
- goto error; |
|
197 |
- } |
|
198 |
- p->host.h_aliases[0]=0; |
|
199 |
- p->host.h_addrtype=AF_INET; |
|
200 |
- p->host.h_length=4; |
|
201 |
- p->host.h_addr_list=malloc(2*sizeof(char*)); |
|
202 |
- if (p->host.h_addr_list==0){ |
|
203 |
- ser_error=E_OUT_OF_MEM; |
|
204 |
- free(p->host.h_name); |
|
205 |
- free(p->host.h_aliases); |
|
206 |
- goto error; |
|
207 |
- } |
|
208 |
- p->host.h_addr_list[1]=0; |
|
209 |
- p->host.h_addr_list[0]=malloc(5); |
|
210 |
- if (p->host.h_addr_list[0]==0){ |
|
211 |
- ser_error=E_OUT_OF_MEM; |
|
212 |
- free(p->host.h_name); |
|
213 |
- free(p->host.h_aliases); |
|
214 |
- free(p->host.h_addr_list); |
|
215 |
- goto error; |
|
216 |
- } |
|
217 |
- memcpy(p->host.h_addr_list[0], (char*)&ip, 4); |
|
218 |
- p->host.h_addr_list[0][4]=0; |
|
219 |
- if (p->port==0) p->port=SIP_PORT; |
|
220 |
- |
|
221 |
- return p; |
|
222 |
- } |
|
223 |
-#endif |
|
224 |
- /* fail over to normal lookup */ |
|
225 | 179 |
|
226 | 180 |
DBG("DEBUG: mk_proxy: doing DNS lookup...\n"); |
227 | 181 |
he=sip_resolvehost(name, &(p->port)); |
... | ... |
@@ -8,6 +8,7 @@ |
8 | 8 |
#include "resolve.h" |
9 | 9 |
#include "dprint.h" |
10 | 10 |
#include "mem/mem.h" |
11 |
+#include "ip_addr.h" |
|
11 | 12 |
|
12 | 13 |
|
13 | 14 |
|
... | ... |
@@ -358,6 +359,7 @@ struct hostent* sip_resolvehost(char* name, unsigned short* port) |
358 | 359 |
struct rdata* head; |
359 | 360 |
struct rdata* l; |
360 | 361 |
struct srv_rdata* srv; |
362 |
+ struct ip_addr* ip; |
|
361 | 363 |
static char tmp[MAX_DNS_NAME]; /* tmp. buff. for SRV lookups */ |
362 | 364 |
int len; |
363 | 365 |
|
... | ... |
@@ -369,6 +371,16 @@ struct hostent* sip_resolvehost(char* name, unsigned short* port) |
369 | 371 |
LOG(L_WARN, "WARNING: sip_resolvehost: domain name too long (%d)," |
370 | 372 |
" unable to perform SRV lookup\n", len); |
371 | 373 |
}else{ |
374 |
+ /* check if it's an ip address */ |
|
375 |
+ if ( ((ip=str2ip(name, len))!=0) |
|
376 |
+#ifdef USE_IPV6 |
|
377 |
+ || ((ip=str2ip6(name, len))!=0) |
|
378 |
+#endif |
|
379 |
+ ){ |
|
380 |
+ /* we are lucky, this is an ip address */ |
|
381 |
+ return ip_addr2he(name,len,ip); |
|
382 |
+ } |
|
383 |
+ |
|
372 | 384 |
memcpy(tmp, SRV_PREFIX, SRV_PREFIX_LEN); |
373 | 385 |
memcpy(tmp+SRV_PREFIX_LEN, name, len+1); /*include the ending 0*/ |
374 | 386 |
|
... | ... |
@@ -11,6 +11,8 @@ |
11 | 11 |
#include <netdb.h> |
12 | 12 |
#include <arpa/nameser.h> |
13 | 13 |
|
14 |
+#include "ip_addr.h" |
|
15 |
+ |
|
14 | 16 |
|
15 | 17 |
#define MAX_QUERY_SIZE 8192 |
16 | 18 |
#define ANS_SIZE 8192 |
... | ... |
@@ -66,28 +68,9 @@ struct rdata* get_record(char* name, int type); |
66 | 68 |
void free_rdata_list(struct rdata* head); |
67 | 69 |
|
68 | 70 |
|
69 |
-/* gethostbyname wrappers |
|
70 |
- * use this, someday htey will use a local cache */ |
|
71 |
- |
|
72 |
-static inline struct hostent* resolvehost(const char* name) |
|
73 |
-{ |
|
74 |
- struct hostent* he; |
|
75 |
- |
|
76 |
-#ifdef DNS_IP_HACK |
|
77 |
-#endif |
|
78 |
- |
|
79 |
- he=gethostbyname(name); /*ipv4*/ |
|
80 | 71 |
|
81 |
-#ifdef USE_IPV6 |
|
82 |
- if(he==0){ |
|
83 |
- /*try ipv6*/ |
|
84 |
- he=gethostbyname2(name, AF_INET6); |
|
85 |
- } |
|
86 |
-#endif |
|
87 |
- return he; |
|
88 |
-} |
|
89 | 72 |
|
90 |
-struct hostent* sip_resolvehost(char* name, unsigned short* port); |
|
73 |
+#define rev_resolvehost(ip) gethostbyaddr((ip)->u.addr, (ip)->len, (ip)->af); |
|
91 | 74 |
|
92 | 75 |
|
93 | 76 |
|
... | ... |
@@ -97,16 +80,53 @@ struct hostent* sip_resolvehost(char* name, unsigned short* port); |
97 | 80 |
(((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 ) |
98 | 81 |
|
99 | 82 |
|
100 |
-#define rev_resolvehost(ip) gethostbyaddr((ip)->u.addr, (ip)->len, (ip)->af); |
|
101 | 83 |
|
102 | 84 |
|
103 | 85 |
|
104 |
-#if 0 |
|
105 |
-/* returns an ip_addr struct.; on error retunrs 0 and sets err (if !=0) |
|
106 |
- * the ip_addr struct is static, so subsequent calls will destroy its |
|
107 |
- * content */ |
|
108 |
-static /*inline*/ struct ip_addr* str2ip6(unsigned char* str, unsigned int len, |
|
109 |
- int* err) |
|
86 |
+/* converts a str to an ipv4 address, returns the address or 0 on error |
|
87 |
+ Warning: the result is a pointer to a statically allocated structure */ |
|
88 |
+static inline struct ip_addr* str2ip(unsigned char* str, unsigned int len) |
|
89 |
+{ |
|
90 |
+ int i; |
|
91 |
+ unsigned char *limit; |
|
92 |
+ unsigned char *init; |
|
93 |
+ static struct ip_addr ip; |
|
94 |
+ |
|
95 |
+ /*init*/ |
|
96 |
+ ip.u.addr32[0]=0; |
|
97 |
+ i=0; |
|
98 |
+ limit=str+len; |
|
99 |
+ init=str; |
|
100 |
+ |
|
101 |
+ for(;str<limit ;str++){ |
|
102 |
+ if (*str=='.'){ |
|
103 |
+ i++; |
|
104 |
+ if (i>3) goto error_dots; |
|
105 |
+ }else if ( (*str <= '9' ) && (*str >= '0') ){ |
|
106 |
+ ip.u.addr[i]=ip.u.addr[i]*10+*str-'0'; |
|
107 |
+ }else{ |
|
108 |
+ //error unknown char |
|
109 |
+ goto error_char; |
|
110 |
+ } |
|
111 |
+ } |
|
112 |
+ ip.af=AF_INET; |
|
113 |
+ ip.len=4; |
|
114 |
+ |
|
115 |
+ return &ip; |
|
116 |
+ |
|
117 |
+error_dots: |
|
118 |
+ DBG("str2ip: ERROR: too many dots in [%.*s]\n", (int)len, init); |
|
119 |
+ return 0; |
|
120 |
+error_char: |
|
121 |
+ DBG("str2ip: WARNING: unexpected char %c in %.*s\n", *str,(int)len, init); |
|
122 |
+ return 0; |
|
123 |
+} |
|
124 |
+ |
|
125 |
+ |
|
126 |
+ |
|
127 |
+/* returns an ip_addr struct.; on error returns 0 |
|
128 |
+ * the ip_addr struct is static, so subsequent calls will destroy its content*/ |
|
129 |
+static inline struct ip_addr* str2ip6(unsigned char* str, unsigned int len) |
|
110 | 130 |
{ |
111 | 131 |
int i, idx1, rest; |
112 | 132 |
int no_colons; |
... | ... |
@@ -143,6 +163,7 @@ static /*inline*/ struct ip_addr* str2ip6(unsigned char* str, unsigned int len, |
143 | 163 |
addr=addr_end; |
144 | 164 |
}else{ |
145 | 165 |
double_colon=1; |
166 |
+ addr[i]=htons(addr[i]); |
|
146 | 167 |
i++; |
147 | 168 |
} |
148 | 169 |
}else if ((hex=HEX2I(*str))>=0){ |
... | ... |
@@ -153,29 +174,70 @@ static /*inline*/ struct ip_addr* str2ip6(unsigned char* str, unsigned int len, |
153 | 174 |
goto error_char; |
154 | 175 |
} |
155 | 176 |
} |
156 |
- |
|
177 |
+ if (no_colons<2) goto error_too_few_colons; |
|
178 |
+ if (!double_colon){ /* not ending in ':' */ |
|
179 |
+ addr[i]=htons(addr[i]); |
|
180 |
+ i++; |
|
181 |
+ } |
|
157 | 182 |
rest=8-i-idx1; |
158 | 183 |
memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short)); |
159 |
- if (err) *err=0; |
|
160 | 184 |
return &ip; |
161 | 185 |
|
162 | 186 |
error_too_many_colons: |
163 | 187 |
DBG("str2ip6: ERROR: too many colons in [%.*s]\n", (int) len, init); |
164 |
- if (err) *err=1; |
|
188 |
+ return 0; |
|
189 |
+ |
|
190 |
+error_too_few_colons: |
|
191 |
+ DBG("str2ip6: ERROR: too few colons in [%.*s]\n", (int) len, init); |
|
165 | 192 |
return 0; |
166 | 193 |
|
167 | 194 |
error_colons: |
168 | 195 |
DBG("str2ip6: ERROR: too many double colons in [%.*s]\n", (int) len, init); |
169 |
- if (err) *err=1; |
|
170 | 196 |
return 0; |
171 | 197 |
|
172 | 198 |
error_char: |
173 | 199 |
DBG("str2ip6: WARNING: unexpected char %c in [%.*s]\n", *str, (int) len, |
174 | 200 |
init); |
175 |
- if (err) *err=1; |
|
176 | 201 |
return 0; |
177 | 202 |
} |
203 |
+ |
|
204 |
+ |
|
205 |
+ |
|
206 |
+struct hostent* sip_resolvehost(char* name, unsigned short* port); |
|
207 |
+ |
|
208 |
+ |
|
209 |
+ |
|
210 |
+/* gethostbyname wrappers |
|
211 |
+ * use this, someday they will use a local cache */ |
|
212 |
+ |
|
213 |
+static inline struct hostent* resolvehost(const char* name) |
|
214 |
+{ |
|
215 |
+ struct hostent* he; |
|
216 |
+#ifdef DNS_IP_HACK |
|
217 |
+ struct ip_addr* ip; |
|
218 |
+ int len; |
|
219 |
+ |
|
220 |
+ len=strlen(name); |
|
221 |
+ /* check if it's an ip address */ |
|
222 |
+ if ( ((ip=str2ip(name, len))!=0) |
|
223 |
+#ifdef USE_IPV6 |
|
224 |
+ || ((ip=str2ip6(name, len))!=0) |
|
225 |
+#endif |
|
226 |
+ ){ |
|
227 |
+ /* we are lucky, this is an ip address */ |
|
228 |
+ return ip_addr2he(name, len, ip); |
|
229 |
+ } |
|
230 |
+ |
|
178 | 231 |
#endif |
232 |
+ he=gethostbyname(name); /*ipv4*/ |
|
233 |
+#ifdef USE_IPV6 |
|
234 |
+ if(he==0){ |
|
235 |
+ /*try ipv6*/ |
|
236 |
+ he=gethostbyname2(name, AF_INET6); |
|
237 |
+ } |
|
238 |
+#endif |
|
239 |
+ return he; |
|
240 |
+} |
|
179 | 241 |
|
180 | 242 |
|
181 | 243 |
|
... | ... |
@@ -1,15 +1,12 @@ |
1 |
-INVITE sip:andrei@iptel.org SIP/2.0 |
|
2 |
-:q |
|
1 |
+INVITE sip:andrei@mobile69 SIP/2.0 |
|
3 | 2 |
Via: SIP/2.0/UDP dorian.fokus.gmd.de |
4 |
-From: "GMD FOKUS iptlab" <sip:jiri@iptel.org>;tag=b96b0300ed30f1286-2f5d |
|
3 |
+From: "test" <sip:andrei@iptel.org>;tag=b96b0300ed30f1286-2f5d |
|
5 | 4 |
Call-ID: b96b0300-88d30f-66da-63aa@195.37.78.190 |
6 | 5 |
CSeq: 101 INVITE |
7 | 6 |
Expires: 180 |
8 | 7 |
Max-Forwards: 0 |
9 |
-User-Agent: Cisco-SIP-IP-Phone/2 |
|
8 |
+User-Agent: testing lookups |
|
10 | 9 |
Accept: application/sdp |
11 |
-Contact: sip:jiri@195.37.78.190:5060 |
|
12 |
-Content-Type: application/sdp |
|
13 | 10 |
Content-Length: 225 |
14 | 11 |
|
15 | 12 |
|
... | ... |
@@ -97,49 +97,6 @@ error_char: |
97 | 97 |
|
98 | 98 |
|
99 | 99 |
|
100 |
-/* converts a str to an ipv4 address, returns the address and sets *err |
|
101 |
- * if error and err!=null |
|
102 |
- */ |
|
103 |
-static inline unsigned int str2ip(unsigned char* str, unsigned int len, |
|
104 |
- int * err) |
|
105 |
-{ |
|
106 |
- unsigned int ret; |
|
107 |
- int i; |
|
108 |
- unsigned char *limit; |
|
109 |
- unsigned char *init; |
|
110 |
- |
|
111 |
- /*init*/ |
|
112 |
- ret=i=0; |
|
113 |
- limit=str+len; |
|
114 |
- init=str; |
|
115 |
- |
|
116 |
- for(;str<limit ;str++){ |
|
117 |
- if (*str=='.'){ |
|
118 |
- i++; |
|
119 |
- if (i>3) goto error_dots; |
|
120 |
- }else if ( (*str <= '9' ) && (*str >= '0') ){ |
|
121 |
- ((unsigned char*)&ret)[i]=((unsigned char*)&ret)[i]*10+ |
|
122 |
- *str-'0'; |
|
123 |
- }else{ |
|
124 |
- //error unknown char |
|
125 |
- goto error_char; |
|
126 |
- } |
|
127 |
- } |
|
128 |
- if (err) *err=0; |
|
129 |
- return ret; |
|
130 |
- |
|
131 |
-error_dots: |
|
132 |
- DBG("str2ip: ERROR: too many dots in [%.*s]\n", (int)len, init); |
|
133 |
- if (err) *err=1; |
|
134 |
- return 0; |
|
135 |
-error_char: |
|
136 |
- DBG("str2ip: WARNING: unexpected char %c in %.*s\n", *str,(int)len, init); |
|
137 |
- if (err) *err=1; |
|
138 |
- return 0; |
|
139 |
-} |
|
140 |
- |
|
141 |
- |
|
142 |
- |
|
143 | 100 |
static inline int btostr( char *p, unsigned char val) |
144 | 101 |
{ |
145 | 102 |
unsigned int a,b,i =0; |