fff774bfd2a1d942aee849d84650cad93d7970f6
[sip-router] / modules / tm / ut.h
1 /*
2  * $Id$
3  *
4  * utilities
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  * History:
31  * -------
32  *  2003-02-13  added proto to uri2proxy (andrei)
33  *  2003-04-09  uri2sock moved from uac.c (janakj)
34  *  2003-04-14  added get_proto to determine protocol from uri unless
35  *              specified explicitly (jiri)
36  *  2003-07-07  get_proto takes now two protos as arguments (andrei)
37  *              tls/sips support for get_proto & uri2proxy (andrei)
38  *  2006-04-13  added uri2dst(), simplified uri2sock() (andrei)
39  *  2006-08-11  dns failover support: uri2dst uses the dns cache and tries to 
40  *               get the first ip for which there is a send sock. (andrei)
41  */
42
43
44 #ifndef _TM_UT_H
45 #define _TM_UT_H
46
47
48 #include "../../proxy.h"
49 #include "../../str.h"
50 #include "../../parser/parse_uri.h"
51 #include "../../dprint.h"
52 #include "../../ut.h"
53 #include "../../ip_addr.h"
54 #include "../../error.h"
55 #include "../../forward.h"
56 #include "../../mem/mem.h"
57 #include "../../parser/msg_parser.h"
58 #include "../../resolve.h"
59 #ifdef USE_DNS_FAILOVER
60 #include "../../dns_cache.h"
61 #include "../../cfg_core.h" /* cfg_get(core, core_cfg, use_dns_failover) */
62 #endif
63
64 /* a forced_proto takes precedence if != PROTO_NONE */
65 inline static enum sip_protos get_proto(enum sip_protos force_proto,
66                                                                                 enum sip_protos proto)
67 {
68         /* calculate transport protocol */
69         switch(force_proto) {
70                 case PROTO_NONE: /* no protocol has been forced -- look at proto */
71                         switch(proto) {
72                                 case PROTO_NONE: /* leave it to dns */
73                                                 return PROTO_NONE;
74                                 case PROTO_UDP:/* transport specified explicitly */
75 #ifdef USE_TCP
76                                 case PROTO_TCP:
77 #endif
78 #ifdef USE_TLS
79                                 case PROTO_TLS:
80 #endif
81 #ifdef USE_SCTP
82                                 case PROTO_SCTP:
83 #endif
84                                                 return proto;
85                                 default:
86                                                 LOG(L_ERR, "ERROR: get_proto: unsupported transport:"
87                                                                 " %d\n", proto );
88                                                 return PROTO_NONE;
89                         }
90                 case PROTO_UDP: /* some protocol has been forced -- take it */
91 #ifdef USE_TCP
92                 case PROTO_TCP:
93 #endif
94 #ifdef USE_TLS
95                 case PROTO_TLS:
96 #endif
97 #ifdef USE_SCTP
98                 case PROTO_SCTP:
99 #endif
100                         return force_proto;
101                 default:
102                         LOG(L_ERR, "ERROR: get_proto: unsupported forced protocol: "
103                                         "%d\n", force_proto);
104                         return PROTO_NONE;
105         }
106 }
107
108
109
110 /*
111  * Convert a URI into a proxy structure
112  */
113 inline static struct proxy_l *uri2proxy( str *uri, int proto )
114 {
115         struct sip_uri parsed_uri;
116         struct proxy_l *p;
117         enum sip_protos uri_proto;
118
119         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
120                 LOG(L_ERR, "ERROR: uri2proxy: bad_uri: %.*s\n",
121                     uri->len, uri->s );
122                 return 0;
123         }
124         
125         if (parsed_uri.type==SIPS_URI_T){
126                 if (parsed_uri.proto==PROTO_UDP) {
127                         LOG(L_ERR, "ERROR: uri2proxy: bad transport for sips uri: %d\n",
128                                         parsed_uri.proto);
129                         return 0;
130                 }else
131                         uri_proto=PROTO_TLS;
132         }else
133                 uri_proto=parsed_uri.proto;
134 #ifdef HONOR_MADDR
135         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
136                 p = mk_proxy(&parsed_uri.maddr_val, 
137                                           parsed_uri.port_no, 
138                                           get_proto(proto, uri_proto));
139                 if (p == 0) {
140                         LOG(L_ERR, "ERROR: uri2proxy: bad maddr param in URI <%.*s>\n",
141                                 uri->len, ZSW(uri->s));
142                         return 0;
143                 }
144         } else
145 #endif
146         p = mk_proxy(&parsed_uri.host, 
147                                   parsed_uri.port_no, 
148                                   get_proto(proto, uri_proto));
149         if (p == 0) {
150                 LOG(L_ERR, "ERROR: uri2proxy: bad host name in URI <%.*s>\n",
151                     uri->len, ZSW(uri->s));
152                 return 0;
153         }
154         
155         return p;
156 }
157
158
159
160 /*
161  * parse uri and return send related information
162  * params: uri - uri in string form
163  *         host - filled with the uri host part
164  *         port - filled with the uri port
165  *         proto - if != PROTO_NONE, this protocol will be forced over the
166  *                 uri_proto, otherwise the uri proto will be used 
167  *                 (value/return)
168  *         comp - compression (if used)
169  * returns 0 on success, < 0 on error
170  */
171 inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
172                                                                         char* proto, short* comp)
173 {
174         struct sip_uri parsed_uri;
175         enum sip_protos uri_proto;
176         
177         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
178                 LOG(L_ERR, "ERROR: get_uri_send_info: bad_uri: %.*s\n",
179                                         uri->len, uri->s );
180                 return -1;
181         }
182         
183         if (parsed_uri.type==SIPS_URI_T){
184                 if (parsed_uri.proto==PROTO_UDP) {
185                         LOG(L_ERR, "ERROR: get_uri_send_info: bad transport for"
186                                                 " sips uri: %d\n", parsed_uri.proto);
187                         return -1;
188                 }else
189                         uri_proto=PROTO_TLS;
190         }else
191                 uri_proto=parsed_uri.proto;
192         
193         *proto= get_proto(*proto, uri_proto);
194 #ifdef USE_COMP
195         *comp=parsed_uri.comp;
196 #endif
197 #ifdef HONOR_MADDR
198         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
199                 *host=parsed_uri.maddr_val;
200                 DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len, 
201                                 parsed_uri.maddr_val.s, parsed_uri.port_no);
202         } else
203 #endif
204                 *host=parsed_uri.host;
205         *port=parsed_uri.port_no;
206         return 0;
207 }
208
209
210
211 /*
212  * Convert a URI into a dest_info structure.
213  * Same as uri2dst, but uses directly force_send_socket instead of msg.
214  * If the uri host resolves to multiple ips and dns_h!=0 the first ip for 
215  *  which a send socket is found will be used. If no send_socket are found,
216  *  the first ip is selected.
217  *
218  * params: dns_h - pointer to a valid dns_srv_handle structure (intialized!) or
219  *                 null. If null or use_dns_failover==0 normal dns lookup will
220  *                 be performed (no failover).
221  *         dst   - will be filled
222  *         force_send_sock - if 0 dst->send_sock will be set to the default 
223  *                 (see get_send_socket2()) 
224  *         sflags - send flags
225  *         uri   - uri in str form
226  *         proto - if != PROTO_NONE, this protocol will be forced over the
227  *                 uri_proto, otherwise the uri proto will be used if set or
228  *                 the proto obtained from the dns lookup
229  * returns 0 on error, dst on success
230  */
231 #ifdef USE_DNS_FAILOVER
232 inline static struct dest_info *uri2dst2(struct dns_srv_handle* dns_h,
233                                                                                 struct dest_info* dst,
234                                                                                 struct socket_info *force_send_socket,
235                                                                                 snd_flags_t sflags,
236                                                                                 str *uri, int proto )
237 #else
238 inline static struct dest_info *uri2dst2(struct dest_info* dst,
239                                                                                 struct socket_info *force_send_socket,
240                                                                                 snd_flags_t sflags,
241                                                                                 str *uri, int proto )
242 #endif
243 {
244         struct sip_uri parsed_uri;
245         enum sip_protos uri_proto;
246         str* host;
247 #ifdef USE_DNS_FAILOVER
248         int ip_found;
249         union sockaddr_union to;
250         int err;
251 #endif
252
253         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
254                 LOG(L_ERR, "ERROR: uri2dst: bad_uri: %.*s\n",
255                     uri->len, uri->s );
256                 return 0;
257         }
258         
259         if (parsed_uri.type==SIPS_URI_T){
260                 if (parsed_uri.proto==PROTO_UDP) {
261                         LOG(L_ERR, "ERROR: uri2dst: bad transport for sips uri: %d\n",
262                                         parsed_uri.proto);
263                         return 0;
264                 }else
265                         uri_proto=PROTO_TLS;
266         }else
267                 uri_proto=parsed_uri.proto;
268         
269         init_dest_info(dst);
270         dst->proto= get_proto(proto, uri_proto);
271 #ifdef USE_COMP
272         dst->comp=parsed_uri.comp;
273 #endif
274         dst->send_flags=sflags;
275 #ifdef HONOR_MADDR
276         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
277                 host=&parsed_uri.maddr_val;
278                 DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len, 
279                                                                 parsed_uri.maddr_val.s, parsed_uri.port_no);
280         } else
281 #endif
282                 host=&parsed_uri.host;
283 #ifdef USE_DNS_FAILOVER
284         if (cfg_get(core, core_cfg, use_dns_failover) && dns_h){
285                 ip_found=0;
286                 do{
287                         /* try all the ips until we find a good send socket */
288                         err=dns_sip_resolve2su(dns_h, &to, host,
289                                                                 parsed_uri.port_no, &dst->proto, dns_flags);
290                         if (err!=0){
291                                 if (ip_found==0){
292                                         if (err!=-E_DNS_EOR)
293                                                 LOG(L_ERR, "ERROR: uri2dst: failed to resolve \"%.*s\" :"
294                                                                 "%s (%d)\n", host->len, ZSW(host->s),
295                                                                         dns_strerror(err), err);
296                                         return 0; /* error, no ip found */
297                                 }
298                                 break;
299                         }
300                         if (ip_found==0){
301                                 dst->to=to;
302                                 ip_found=1;
303                         }
304                         dst->send_sock = get_send_socket2(force_send_socket, &to,
305                                                                                                 dst->proto, 0);
306                         if (dst->send_sock){
307                                 dst->to=to;
308                                 return dst; /* found a good one */
309                         }
310                 }while(dns_srv_handle_next(dns_h, err));
311                 ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
312                                 ZSW(host->s), dst->to.s.sa_family);
313                 /* try to continue */
314                 return dst;
315         }
316 #endif
317         if (sip_hostport2su(&dst->to, host, parsed_uri.port_no, &dst->proto)!=0){
318                 ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
319                 return 0;
320         }
321         dst->send_sock = get_send_socket2(force_send_socket, &dst->to,
322                                                                                 dst->proto, 0);
323         if (dst->send_sock==0) {
324                 ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
325                 /* ser_error = E_NO_SOCKET;*/
326                 /* try to continue */
327         }
328         return dst;
329 }
330
331
332
333 /*
334  * Convert a URI into a dest_info structure
335  * If the uri host resolves to multiple ips and dns_h!=0 the first ip for 
336  *  which a send socket is found will be used. If no send_socket are found,
337  *  the first ip is selected.
338  *
339  * params: dns_h - pointer to a valid dns_srv_handle structure (intialized!) or
340  *                 null. If null or use_dns_failover==0 normal dns lookup will
341  *                 be performed (no failover).
342  *         dst   - will be filled
343  *         msg   -  sip message used to set dst->send_sock and dst->send_flags,
344  *                 if 0 dst->send_sock will be set to the default w/o using 
345  *                  msg->force_send_socket (see get_send_socket()) and the 
346  *                  send_flags will be set to 0.
347  *         uri   - uri in str form
348  *         proto - if != PROTO_NONE, this protocol will be forced over the
349  *                 uri_proto, otherwise the uri proto will be used if set or
350  *                 the proto obtained from the dns lookup
351  * returns 0 on error, dst on success
352  */
353 #ifdef USE_DNS_FAILOVER
354 inline static struct dest_info *uri2dst(struct dns_srv_handle* dns_h,
355                                                                                 struct dest_info* dst,
356                                                                                 struct sip_msg *msg, str *uri, 
357                                                                                         int proto )
358 {
359         snd_flags_t sflags;
360         if (msg)
361                 return uri2dst2(dns_h, dst, msg->force_send_socket,
362                                                         msg->fwd_send_flags, uri, proto);
363         SND_FLAGS_INIT(&sflags);
364         return uri2dst2(dns_h, dst, 0, sflags, uri, proto);
365 }
366 #else
367 inline static struct dest_info *uri2dst(struct dest_info* dst,
368                                                                                 struct sip_msg *msg, str *uri, 
369                                                                                         int proto )
370 {
371         snd_flags_t sflags;
372         if (msg)
373                 return uri2dst2(dst, msg->force_send_socket, msg->fwd_send_flags,
374                                                 uri, proto);
375         SND_FLAGS_INIT(&sflags);
376         return uri2dst2(dst, 0, sflags, uri, proto);
377 }
378 #endif /* USE_DNS_FAILOVER */
379
380
381
382 #if 0
383 /*
384  * Convert a URI into the corresponding sockaddr_union (address to send to) and
385  *  send socket_info (socket/address from which to send)
386  *  to_su is filled with the destination and the socket_info that will be 
387  *  used for sending is returned.
388  *  On error return 0.
389  *
390  *  NOTE: this function is deprecated, you should use uri2dst instead
391  */
392 static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
393                                                                         union sockaddr_union *to_su, int proto)
394 {
395         struct dest_info dst;
396
397         if (uri2dst(&dst, msg, uri, proto)==0){
398                 LOG(L_ERR, "ERROR: uri2sock: Can't create a dst proxy\n");
399                 ser_error=E_BAD_ADDRESS;
400                 return 0;
401         }
402         *to_su=dst.to; /* copy su */
403         
404         /* we use dst->send_socket since uri2dst just set it correctly*/
405         if (dst.send_sock==0) {
406                 LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
407                     to_su->s.sa_family);
408                 ser_error = E_NO_SOCKET;
409         }
410         return dst.send_sock;
411 }
412 #endif
413
414 #endif /* _TM_UT_H */