modules/tm/ut.h

00001 /*
00002  * $Id$
00003  *
00004  * utilities
00005  *
00006  *
00007  * Copyright (C) 2001-2003 FhG Fokus
00008  *
00009  * This file is part of ser, a free SIP server.
00010  *
00011  * ser is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * For a license to use the ser software under conditions
00017  * other than those described here, or to purchase support for this
00018  * software, please contact iptel.org by e-mail at the following addresses:
00019  *    info@iptel.org
00020  *
00021  * ser is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License 
00027  * along with this program; if not, write to the Free Software 
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00029  *
00030  * History:
00031  * -------
00032  *  2003-02-13  added proto to uri2proxy (andrei)
00033  *  2003-04-09  uri2sock moved from uac.c (janakj)
00034  *  2003-04-14  added get_proto to determine protocol from uri unless
00035  *              specified explicitly (jiri)
00036  *  2003-07-07  get_proto takes now two protos as arguments (andrei)
00037  *              tls/sips support for get_proto & uri2proxy (andrei)
00038  *  2006-04-13  added uri2dst(), simplified uri2sock() (andrei)
00039  *  2006-08-11  dns failover support: uri2dst uses the dns cache and tries to 
00040  *               get the first ip for which there is a send sock. (andrei)
00041  */
00042 
00043 
00044 #ifndef _TM_UT_H
00045 #define _TM_UT_H
00046 
00047 
00048 #include "../../proxy.h"
00049 #include "../../str.h"
00050 #include "../../parser/parse_uri.h"
00051 #include "../../dprint.h"
00052 #include "../../ut.h"
00053 #include "../../ip_addr.h"
00054 #include "../../error.h"
00055 #include "../../forward.h"
00056 #include "../../mem/mem.h"
00057 #include "../../parser/msg_parser.h"
00058 #include "../../resolve.h"
00059 #ifdef USE_DNS_FAILOVER
00060 #include "../../dns_cache.h"
00061 #include "../../cfg_core.h" /* cfg_get(core, core_cfg, use_dns_failover) */
00062 #endif
00063 
00064 
00066 #define tm_skip_hf(_hf) \
00067         (((_hf)->type == HDR_FROM_T)  || \
00068         ((_hf)->type == HDR_TO_T)     || \
00069         ((_hf)->type == HDR_CALLID_T) || \
00070         ((_hf)->type == HDR_CSEQ_T))
00071 
00072 
00073 /* a forced_proto takes precedence if != PROTO_NONE */
00074 inline static enum sip_protos get_proto(enum sip_protos force_proto,
00075                                                                                 enum sip_protos proto)
00076 {
00077         /* calculate transport protocol */
00078         switch(force_proto) {
00079                 case PROTO_NONE: /* no protocol has been forced -- look at proto */
00080                         switch(proto) {
00081                                 case PROTO_NONE: /* leave it to dns */
00082                                                 return PROTO_NONE;
00083                                 case PROTO_UDP:/* transport specified explicitly */
00084 #ifdef USE_TCP
00085                                 case PROTO_TCP:
00086 #endif
00087 #ifdef USE_TLS
00088                                 case PROTO_TLS:
00089 #endif
00090 #ifdef USE_SCTP
00091                                 case PROTO_SCTP:
00092 #endif
00093                                                 return proto;
00094                                 default:
00095                                                 LOG(L_ERR, "ERROR: get_proto: unsupported transport:"
00096                                                                 " %d\n", proto );
00097                                                 return PROTO_NONE;
00098                         }
00099                 case PROTO_UDP: /* some protocol has been forced -- take it */
00100 #ifdef USE_TCP
00101                 case PROTO_TCP:
00102 #endif
00103 #ifdef USE_TLS
00104                 case PROTO_TLS:
00105 #endif
00106 #ifdef USE_SCTP
00107                 case PROTO_SCTP:
00108 #endif
00109                         return force_proto;
00110                 default:
00111                         LOG(L_ERR, "ERROR: get_proto: unsupported forced protocol: "
00112                                         "%d\n", force_proto);
00113                         return PROTO_NONE;
00114         }
00115 }
00116 
00117 
00118 
00119 /*
00120  * Convert a URI into a proxy structure
00121  */
00122 inline static struct proxy_l *uri2proxy( str *uri, int proto )
00123 {
00124         struct sip_uri parsed_uri;
00125         struct proxy_l *p;
00126         enum sip_protos uri_proto;
00127 
00128         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
00129                 LOG(L_ERR, "ERROR: uri2proxy: bad_uri: %.*s\n",
00130                     uri->len, uri->s );
00131                 return 0;
00132         }
00133         
00134         if (parsed_uri.type==SIPS_URI_T){
00135                 if (parsed_uri.proto==PROTO_UDP) {
00136                         LOG(L_ERR, "ERROR: uri2proxy: bad transport for sips uri: %d\n",
00137                                         parsed_uri.proto);
00138                         return 0;
00139                 }else
00140                         uri_proto=PROTO_TLS;
00141         }else
00142                 uri_proto=parsed_uri.proto;
00143 #ifdef HONOR_MADDR
00144         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
00145                 p = mk_proxy(&parsed_uri.maddr_val, 
00146                                           parsed_uri.port_no, 
00147                                           get_proto(proto, uri_proto));
00148                 if (p == 0) {
00149                         LOG(L_ERR, "ERROR: uri2proxy: bad maddr param in URI <%.*s>\n",
00150                                 uri->len, ZSW(uri->s));
00151                         return 0;
00152                 }
00153         } else
00154 #endif
00155         p = mk_proxy(&parsed_uri.host, 
00156                                   parsed_uri.port_no, 
00157                                   get_proto(proto, uri_proto));
00158         if (p == 0) {
00159                 LOG(L_ERR, "ERROR: uri2proxy: bad host name in URI <%.*s>\n",
00160                     uri->len, ZSW(uri->s));
00161                 return 0;
00162         }
00163         
00164         return p;
00165 }
00166 
00167 
00168 
00169 /*
00170  * parse uri and return send related information
00171  * params: uri - uri in string form
00172  *         host - filled with the uri host part
00173  *         port - filled with the uri port
00174  *         proto - if != PROTO_NONE, this protocol will be forced over the
00175  *                 uri_proto, otherwise the uri proto will be used 
00176  *                 (value/return)
00177  *         comp - compression (if used)
00178  * returns 0 on success, < 0 on error
00179  */
00180 inline static int get_uri_send_info(str* uri, str* host, unsigned short* port,
00181                                                                         char* proto, short* comp)
00182 {
00183         struct sip_uri parsed_uri;
00184         enum sip_protos uri_proto;
00185         
00186         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
00187                 LOG(L_ERR, "ERROR: get_uri_send_info: bad_uri: %.*s\n",
00188                                         uri->len, uri->s );
00189                 return -1;
00190         }
00191         
00192         if (parsed_uri.type==SIPS_URI_T){
00193                 if (parsed_uri.proto==PROTO_UDP) {
00194                         LOG(L_ERR, "ERROR: get_uri_send_info: bad transport for"
00195                                                 " sips uri: %d\n", parsed_uri.proto);
00196                         return -1;
00197                 }else
00198                         uri_proto=PROTO_TLS;
00199         }else
00200                 uri_proto=parsed_uri.proto;
00201         
00202         *proto= get_proto(*proto, uri_proto);
00203 #ifdef USE_COMP
00204         *comp=parsed_uri.comp;
00205 #endif
00206 #ifdef HONOR_MADDR
00207         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
00208                 *host=parsed_uri.maddr_val;
00209                 DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len, 
00210                                 parsed_uri.maddr_val.s, parsed_uri.port_no);
00211         } else
00212 #endif
00213                 *host=parsed_uri.host;
00214         *port=parsed_uri.port_no;
00215         return 0;
00216 }
00217 
00218 
00219 
00220 /*
00221  * Convert a URI into a dest_info structure.
00222  * Same as uri2dst, but uses directly force_send_socket instead of msg.
00223  * If the uri host resolves to multiple ips and dns_h!=0 the first ip for 
00224  *  which a send socket is found will be used. If no send_socket are found,
00225  *  the first ip is selected.
00226  *
00227  * params: dns_h - pointer to a valid dns_srv_handle structure (intialized!) or
00228  *                 null. If null or use_dns_failover==0 normal dns lookup will
00229  *                 be performed (no failover).
00230  *         dst   - will be filled
00231  *         force_send_sock - if 0 dst->send_sock will be set to the default 
00232  *                 (see get_send_socket2()) 
00233  *         sflags - send flags
00234  *         uri   - uri in str form
00235  *         proto - if != PROTO_NONE, this protocol will be forced over the
00236  *                 uri_proto, otherwise the uri proto will be used if set or
00237  *                 the proto obtained from the dns lookup
00238  * returns 0 on error, dst on success
00239  */
00240 #ifdef USE_DNS_FAILOVER
00241 inline static struct dest_info *uri2dst2(struct dns_srv_handle* dns_h,
00242                                                                                 struct dest_info* dst,
00243                                                                                 struct socket_info *force_send_socket,
00244                                                                                 snd_flags_t sflags,
00245                                                                                 str *uri, int proto )
00246 #else
00247 inline static struct dest_info *uri2dst2(struct dest_info* dst,
00248                                                                                 struct socket_info *force_send_socket,
00249                                                                                 snd_flags_t sflags,
00250                                                                                 str *uri, int proto )
00251 #endif
00252 {
00253         struct sip_uri parsed_uri;
00254         enum sip_protos uri_proto;
00255         str* host;
00256 #ifdef USE_DNS_FAILOVER
00257         int ip_found;
00258         union sockaddr_union to;
00259         int err;
00260 #endif
00261 
00262         if (parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
00263                 LOG(L_ERR, "ERROR: uri2dst: bad_uri: %.*s\n",
00264                     uri->len, uri->s );
00265                 return 0;
00266         }
00267         
00268         if (parsed_uri.type==SIPS_URI_T){
00269                 if (parsed_uri.proto==PROTO_UDP) {
00270                         LOG(L_ERR, "ERROR: uri2dst: bad transport for sips uri: %d\n",
00271                                         parsed_uri.proto);
00272                         return 0;
00273                 }else
00274                         uri_proto=PROTO_TLS;
00275         }else
00276                 uri_proto=parsed_uri.proto;
00277         
00278         init_dest_info(dst);
00279         dst->proto= get_proto(proto, uri_proto);
00280 #ifdef USE_COMP
00281         dst->comp=parsed_uri.comp;
00282 #endif
00283         dst->send_flags=sflags;
00284 #ifdef HONOR_MADDR
00285         if (parsed_uri.maddr_val.s && parsed_uri.maddr_val.len) {
00286                 host=&parsed_uri.maddr_val;
00287                 DBG("maddr dst: %.*s:%d\n", parsed_uri.maddr_val.len, 
00288                                                                 parsed_uri.maddr_val.s, parsed_uri.port_no);
00289         } else
00290 #endif
00291                 host=&parsed_uri.host;
00292 #ifdef USE_DNS_FAILOVER
00293         if (cfg_get(core, core_cfg, use_dns_failover) && dns_h){
00294                 ip_found=0;
00295                 do{
00296                         /* try all the ips until we find a good send socket */
00297                         err=dns_sip_resolve2su(dns_h, &to, host,
00298                                                                 parsed_uri.port_no, &dst->proto, dns_flags);
00299                         if (err!=0){
00300                                 if (ip_found==0){
00301                                         if (err!=-E_DNS_EOR)
00302                                                 LOG(L_ERR, "ERROR: uri2dst: failed to resolve \"%.*s\" :"
00303                                                                 "%s (%d)\n", host->len, ZSW(host->s),
00304                                                                         dns_strerror(err), err);
00305                                         return 0; /* error, no ip found */
00306                                 }
00307                                 break;
00308                         }
00309                         if (ip_found==0){
00310                                 dst->to=to;
00311                                 ip_found=1;
00312                         }
00313                         dst->send_sock = get_send_socket2(force_send_socket, &to,
00314                                                                                                 dst->proto, 0);
00315                         if (dst->send_sock){
00316                                 dst->to=to;
00317                                 return dst; /* found a good one */
00318                         }
00319                 }while(dns_srv_handle_next(dns_h, err));
00320                 ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
00321                                 ZSW(host->s), dst->to.s.sa_family);
00322                 /* try to continue */
00323                 return dst;
00324         }
00325 #endif
00326         if (sip_hostport2su(&dst->to, host, parsed_uri.port_no, &dst->proto)!=0){
00327                 ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
00328                 return 0;
00329         }
00330         dst->send_sock = get_send_socket2(force_send_socket, &dst->to,
00331                                                                                 dst->proto, 0);
00332         if (dst->send_sock==0) {
00333                 ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
00334                 /* ser_error = E_NO_SOCKET;*/
00335                 /* try to continue */
00336         }
00337         return dst;
00338 }
00339 
00340 
00341 
00342 /*
00343  * Convert a URI into a dest_info structure
00344  * If the uri host resolves to multiple ips and dns_h!=0 the first ip for 
00345  *  which a send socket is found will be used. If no send_socket are found,
00346  *  the first ip is selected.
00347  *
00348  * params: dns_h - pointer to a valid dns_srv_handle structure (intialized!) or
00349  *                 null. If null or use_dns_failover==0 normal dns lookup will
00350  *                 be performed (no failover).
00351  *         dst   - will be filled
00352  *         msg   -  sip message used to set dst->send_sock and dst->send_flags,
00353  *                 if 0 dst->send_sock will be set to the default w/o using 
00354  *                  msg->force_send_socket (see get_send_socket()) and the 
00355  *                  send_flags will be set to 0.
00356  *         uri   - uri in str form
00357  *         proto - if != PROTO_NONE, this protocol will be forced over the
00358  *                 uri_proto, otherwise the uri proto will be used if set or
00359  *                 the proto obtained from the dns lookup
00360  * returns 0 on error, dst on success
00361  */
00362 #ifdef USE_DNS_FAILOVER
00363 inline static struct dest_info *uri2dst(struct dns_srv_handle* dns_h,
00364                                                                                 struct dest_info* dst,
00365                                                                                 struct sip_msg *msg, str *uri, 
00366                                                                                         int proto )
00367 {
00368         snd_flags_t sflags;
00369         if (msg)
00370                 return uri2dst2(dns_h, dst, msg->force_send_socket,
00371                                                         msg->fwd_send_flags, uri, proto);
00372         SND_FLAGS_INIT(&sflags);
00373         return uri2dst2(dns_h, dst, 0, sflags, uri, proto);
00374 }
00375 #else
00376 inline static struct dest_info *uri2dst(struct dest_info* dst,
00377                                                                                 struct sip_msg *msg, str *uri, 
00378                                                                                         int proto )
00379 {
00380         snd_flags_t sflags;
00381         if (msg)
00382                 return uri2dst2(dst, msg->force_send_socket, msg->fwd_send_flags,
00383                                                 uri, proto);
00384         SND_FLAGS_INIT(&sflags);
00385         return uri2dst2(dst, 0, sflags, uri, proto);
00386 }
00387 #endif /* USE_DNS_FAILOVER */
00388 
00389 #endif /* _TM_UT_H */