everything: shotgun attempt to put PROTO_WS and PROTO_WSS across core and in modules...
[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
65 /*! Which header fields should be skipped */
66 #define tm_skip_hf(_hf) \
67         (((_hf)->type == HDR_FROM_T)  || \
68         ((_hf)->type == HDR_TO_T)     || \
69         ((_hf)->type == HDR_CALLID_T) || \
70         ((_hf)->type == HDR_CSEQ_T))
71
72
73 /* a forced_proto takes precedence if != PROTO_NONE */
74 inline static enum sip_protos get_proto(enum sip_protos force_proto,
75                                                                                 enum sip_protos proto)
76 {
77         /* calculate transport protocol */
78         switch(force_proto) {
79                 case PROTO_NONE: /* no protocol has been forced -- look at proto */
80                         switch(proto) {
81                                 case PROTO_NONE: /* leave it to dns */
82                                                 return PROTO_NONE;
83                                 case PROTO_UDP:/* transport specified explicitly */
84 #ifdef USE_TCP
85                                 case PROTO_TCP:
86                                 case PROTO_WS:
87 #endif
88 #ifdef USE_TLS
89                                 case PROTO_TLS:
90 #endif
91 #ifdef USE_SCTP
92                                 case PROTO_SCTP:
93 #endif
94                                                 return proto;
95                                 case PROTO_WSS: /* should never see ;transport=wss */
96                                 default:
97                                                 LOG(L_ERR, "ERROR: get_proto: unsupported transport:"
98                                                                 " %d\n", proto );
99                                                 return PROTO_NONE;
100                         }
101                 case PROTO_UDP: /* some protocol has been forced -- take it */
102 #ifdef USE_TCP
103                 case PROTO_TCP:
104                 case PROTO_WS:
105 #endif
106 #ifdef USE_TLS
107                 case PROTO_TLS:
108                 case PROTO_WSS:
109 #endif
110 #ifdef USE_SCTP
111                 case PROTO_SCTP:
112 #endif
113                         return force_proto;
114                 default:
115                         LOG(L_ERR, "ERROR: get_proto: unsupported forced protocol: "
116                                         "%d\n", force_proto);
117                         return PROTO_NONE;
118         }
119 }
120
121
122
123 /*
124  * Convert a URI into a proxy structure
125  */
126 inline static struct proxy_l *uri2proxy( str *uri, int proto )
127 {
128         struct sip_uri parsed_uri;
129         struct proxy_l *p;
130         enum sip_protos uri_proto;
131
132         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
133                 LOG(L_ERR, "ERROR: uri2proxy: bad_uri: %.*s\n",
134                     uri->len, uri->s );
135                 return 0;
136         }
137         
138         if (parsed_uri.type==SIPS_URI_T){
139                 if (parsed_uri.proto==PROTO_UDP) {
140                         LOG(L_ERR, "ERROR: uri2proxy: bad transport for sips uri: %d\n",
141                                         parsed_uri.proto);
142                         return 0;
143                 }else if (parsed_uri.proto != PROTO_WS)
144                         uri_proto=PROTO_TLS;
145                 else
146                         uri_proto=PROTO_WS;
147         }else
148                 uri_proto=parsed_uri.proto;
149 #ifdef HONOR_MADDR
150         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
151                 p = mk_proxy(&parsed_uri.maddr_val, 
152                                           parsed_uri.port_no, 
153                                           get_proto(proto, uri_proto));
154                 if (p == 0) {
155                         LOG(L_ERR, "ERROR: uri2proxy: bad maddr param in URI <%.*s>\n",
156                                 uri->len, ZSW(uri->s));
157                         return 0;
158                 }
159         } else
160 #endif
161         p = mk_proxy(&parsed_uri.host, 
162                                   parsed_uri.port_no, 
163                                   get_proto(proto, uri_proto));
164         if (p == 0) {
165                 LOG(L_ERR, "ERROR: uri2proxy: bad host name in URI <%.*s>\n",
166                     uri->len, ZSW(uri->s));
167                 return 0;
168         }
169         
170         return p;
171 }
172
173
174
175 /*
176  * parse uri and return send related information
177  * params: uri - uri in string form
178  *         host - filled with the uri host part
179  *         port - filled with the uri port
180  *         proto - if != PROTO_NONE, this protocol will be forced over the
181  *                 uri_proto, otherwise the uri proto will be used 
182  *                 (value/return)
183  *         comp - compression (if used)
184  * returns 0 on success, < 0 on error
185  */
186 inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
187                                                                         char* proto, short* comp)
188 {
189         struct sip_uri parsed_uri;
190         enum sip_protos uri_proto;
191         
192         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
193                 LOG(L_ERR, "ERROR: get_uri_send_info: bad_uri: %.*s\n",
194                                         uri->len, uri->s );
195                 return -1;
196         }
197         
198         if (parsed_uri.type==SIPS_URI_T){
199                 if (parsed_uri.proto==PROTO_UDP) {
200                         LOG(L_ERR, "ERROR: get_uri_send_info: bad transport for"
201                                                 " sips uri: %d\n", parsed_uri.proto);
202                         return -1;
203                 }else if (parsed_uri.proto != PROTO_WS)
204                         uri_proto=PROTO_TLS;
205                 else
206                         uri_proto=PROTO_WS;
207         }else
208                 uri_proto=parsed_uri.proto;
209         
210         *proto= get_proto(*proto, uri_proto);
211 #ifdef USE_COMP
212         *comp=parsed_uri.comp;
213 #endif
214 #ifdef HONOR_MADDR
215         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
216                 *host=parsed_uri.maddr_val;
217                 DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len, 
218                                 parsed_uri.maddr_val.s, parsed_uri.port_no);
219         } else
220 #endif
221                 *host=parsed_uri.host;
222         *port=parsed_uri.port_no;
223         return 0;
224 }
225
226
227
228 /*
229  * Convert a URI into a dest_info structure.
230  * Same as uri2dst, but uses directly force_send_socket instead of msg.
231  * If the uri host resolves to multiple ips and dns_h!=0 the first ip for 
232  *  which a send socket is found will be used. If no send_socket are found,
233  *  the first ip is selected.
234  *
235  * params: dns_h - pointer to a valid dns_srv_handle structure (intialized!) or
236  *                 null. If null or use_dns_failover==0 normal dns lookup will
237  *                 be performed (no failover).
238  *         dst   - will be filled
239  *         force_send_sock - if 0 dst->send_sock will be set to the default 
240  *                 (see get_send_socket2()) 
241  *         sflags - send flags
242  *         uri   - uri in str form
243  *         proto - if != PROTO_NONE, this protocol will be forced over the
244  *                 uri_proto, otherwise the uri proto will be used if set or
245  *                 the proto obtained from the dns lookup
246  * returns 0 on error, dst on success
247  */
248 #ifdef USE_DNS_FAILOVER
249 inline static struct dest_info *uri2dst2(struct dns_srv_handle* dns_h,
250                                                                                 struct dest_info* dst,
251                                                                                 struct socket_info *force_send_socket,
252                                                                                 snd_flags_t sflags,
253                                                                                 str *uri, int proto )
254 #else
255 inline static struct dest_info *uri2dst2(struct dest_info* dst,
256                                                                                 struct socket_info *force_send_socket,
257                                                                                 snd_flags_t sflags,
258                                                                                 str *uri, int proto )
259 #endif
260 {
261         struct sip_uri parsed_uri;
262         enum sip_protos uri_proto;
263         str* host;
264 #ifdef USE_DNS_FAILOVER
265         int ip_found;
266         union sockaddr_union to;
267         int err;
268 #endif
269
270         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
271                 LOG(L_ERR, "ERROR: uri2dst: bad_uri: %.*s\n",
272                     uri->len, uri->s );
273                 return 0;
274         }
275         
276         if (parsed_uri.type==SIPS_URI_T){
277                 if (parsed_uri.proto==PROTO_UDP) {
278                         LOG(L_ERR, "ERROR: uri2dst: bad transport for sips uri: %d\n",
279                                         parsed_uri.proto);
280                         return 0;
281                 }else if (parsed_uri.proto!=PROTO_WS)
282                         uri_proto=PROTO_TLS;
283                 else
284                         uri_proto=PROTO_WS;
285         }else
286                 uri_proto=parsed_uri.proto;
287         
288         init_dest_info(dst);
289         dst->proto= get_proto(proto, uri_proto);
290 #ifdef USE_COMP
291         dst->comp=parsed_uri.comp;
292 #endif
293         dst->send_flags=sflags;
294 #ifdef HONOR_MADDR
295         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
296                 host=&parsed_uri.maddr_val;
297                 DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len, 
298                                                                 parsed_uri.maddr_val.s, parsed_uri.port_no);
299         } else
300 #endif
301                 host=&parsed_uri.host;
302 #ifdef USE_DNS_FAILOVER
303         if (cfg_get(core, core_cfg, use_dns_failover) && dns_h){
304                 ip_found=0;
305                 do{
306                         /* try all the ips until we find a good send socket */
307                         err=dns_sip_resolve2su(dns_h, &to, host,
308                                                                 parsed_uri.port_no, &dst->proto, dns_flags);
309                         if (err!=0){
310                                 if (ip_found==0){
311                                         if (err!=-E_DNS_EOR)
312                                                 LOG(L_ERR, "ERROR: uri2dst: failed to resolve \"%.*s\" :"
313                                                                 "%s (%d)\n", host->len, ZSW(host->s),
314                                                                         dns_strerror(err), err);
315                                         return 0; /* error, no ip found */
316                                 }
317                                 break;
318                         }
319                         if (ip_found==0){
320                                 dst->to=to;
321                                 ip_found=1;
322                         }
323                         dst->send_sock = get_send_socket2(force_send_socket, &to,
324                                                                                                 dst->proto, 0);
325                         if (dst->send_sock){
326                                 dst->to=to;
327                                 return dst; /* found a good one */
328                         }
329                 }while(dns_srv_handle_next(dns_h, err));
330                 ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
331                                 ZSW(host->s), dst->to.s.sa_family);
332                 /* try to continue */
333                 return dst;
334         }
335 #endif
336         if (sip_hostport2su(&dst->to, host, parsed_uri.port_no, &dst->proto)!=0){
337                 ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
338                 return 0;
339         }
340         dst->send_sock = get_send_socket2(force_send_socket, &dst->to,
341                                                                                 dst->proto, 0);
342         if (dst->send_sock==0) {
343                 ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
344                 /* ser_error = E_NO_SOCKET;*/
345                 /* try to continue */
346         }
347         return dst;
348 }
349
350
351
352 /*
353  * Convert a URI into a dest_info structure
354  * If the uri host resolves to multiple ips and dns_h!=0 the first ip for 
355  *  which a send socket is found will be used. If no send_socket are found,
356  *  the first ip is selected.
357  *
358  * params: dns_h - pointer to a valid dns_srv_handle structure (intialized!) or
359  *                 null. If null or use_dns_failover==0 normal dns lookup will
360  *                 be performed (no failover).
361  *         dst   - will be filled
362  *         msg   -  sip message used to set dst->send_sock and dst->send_flags,
363  *                 if 0 dst->send_sock will be set to the default w/o using 
364  *                  msg->force_send_socket (see get_send_socket()) and the 
365  *                  send_flags will be set to 0.
366  *         uri   - uri in str form
367  *         proto - if != PROTO_NONE, this protocol will be forced over the
368  *                 uri_proto, otherwise the uri proto will be used if set or
369  *                 the proto obtained from the dns lookup
370  * returns 0 on error, dst on success
371  */
372 #ifdef USE_DNS_FAILOVER
373 inline static struct dest_info *uri2dst(struct dns_srv_handle* dns_h,
374                                                                                 struct dest_info* dst,
375                                                                                 struct sip_msg *msg, str *uri, 
376                                                                                         int proto )
377 {
378         snd_flags_t sflags;
379         if (msg)
380                 return uri2dst2(dns_h, dst, msg->force_send_socket,
381                                                         msg->fwd_send_flags, uri, proto);
382         SND_FLAGS_INIT(&sflags);
383         return uri2dst2(dns_h, dst, 0, sflags, uri, proto);
384 }
385 #else
386 inline static struct dest_info *uri2dst(struct dest_info* dst,
387                                                                                 struct sip_msg *msg, str *uri, 
388                                                                                         int proto )
389 {
390         snd_flags_t sflags;
391         if (msg)
392                 return uri2dst2(dst, msg->force_send_socket, msg->fwd_send_flags,
393                                                 uri, proto);
394         SND_FLAGS_INIT(&sflags);
395         return uri2dst2(dst, 0, sflags, uri, proto);
396 }
397 #endif /* USE_DNS_FAILOVER */
398
399 #endif /* _TM_UT_H */