nathelper.c

Go to the documentation of this file.
00001 /* $Id: nathelper.c 5504 2009-01-23 14:08:20Z carstenbock $
00002  *
00003  * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
00004  *
00005  * This file is part of Kamailio, a free SIP server.
00006  *
00007  * Kamailio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version
00011  *
00012  * Kamailio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * History:
00022  * ---------
00023  * 2003-10-09  nat_uac_test introduced (jiri)
00024  *
00025  * 2003-11-06   nat_uac_test permitted from onreply_route (jiri)
00026  *
00027  * 2003-12-01   unforce_rtp_proxy introduced (sobomax)
00028  *
00029  * 2004-01-07  RTP proxy support updated to support new version of the
00030  *    RTP proxy (20040107).
00031  *
00032  *    force_rtp_proxy() now inserts a special flag
00033  *    into the SDP body to indicate that this session already
00034  *    proxied and ignores sessions with such flag.
00035  *
00036  *    Added run-time check for version of command protocol
00037  *    supported by the RTP proxy.
00038  *
00039  * 2004-01-16   Integrated slightly modified patch from Tristan Colgate,
00040  *    force_rtp_proxy function with IP as a parameter (janakj)
00041  *
00042  * 2004-01-28  nat_uac_test extended to allow testing SDP body (sobomax)
00043  *
00044  *    nat_uac_test extended to allow testing top Via (sobomax)
00045  *
00046  * 2004-02-21  force_rtp_proxy now accepts option argument, which
00047  *    consists of string of chars, each of them turns "on"
00048  *    some feature, currently supported ones are:
00049  *
00050  *     `a' - flags that UA from which message is received
00051  *           doesn't support symmetric RTP;
00052  *     `l' - force "lookup", that is, only rewrite SDP when
00053  *           corresponding session is already exists in the
00054  *           RTP proxy. Only makes sense for SIP requests,
00055  *           replies are always processed in "lookup" mode;
00056  *     `i' - flags that message is received from UA in the
00057  *           LAN. Only makes sense when RTP proxy is running
00058  *           in the bridge mode.
00059  *
00060  *    force_rtp_proxy can now be invoked without any arguments,
00061  *    as previously, with one argument - in this case argument
00062  *    is treated as option string and with two arguments, in
00063  *    which case 1st argument is option string and the 2nd
00064  *    one is IP address which have to be inserted into
00065  *    SDP (IP address on which RTP proxy listens).
00066  *
00067  * 2004-03-12  Added support for IPv6 addresses in SDPs. Particularly,
00068  *    force_rtp_proxy now can work with IPv6-aware RTP proxy,
00069  *    replacing IPv4 address in SDP with IPv6 one and vice versa.
00070  *    This allows creating full-fledged IPv4<->IPv6 gateway.
00071  *    See 4to6.cfg file for example.
00072  *
00073  *    Two new options added into force_rtp_proxy:
00074  *
00075  *     `f' - instructs nathelper to ignore marks inserted
00076  *           by another nathelper in transit to indicate
00077  *           that the session is already goes through another
00078  *           proxy. Allows creating chain of proxies.
00079  *     `r' - flags that IP address in SDP should be trusted.
00080  *           Without this flag, nathelper ignores address in the
00081  *           SDP and uses source address of the SIP message
00082  *           as media address which is passed to the RTP proxy.
00083  *
00084  *    Protocol between nathelper and RTP proxy in bridge
00085  *    mode has been slightly changed. Now RTP proxy expects SER
00086  *    to provide 2 flags when creating or updating session
00087  *    to indicate direction of this session. Each of those
00088  *    flags can be either `e' or `i'. For example `ei' means
00089  *    that we received INVITE from UA on the "external" network
00090  *    network and will send it to the UA on "internal" one.
00091  *    Also possible `ie' (internal->external), `ii'
00092  *    (internal->internal) and `ee' (external->external). See
00093  *    example file alg.cfg for details.
00094  *
00095  * 2004-03-15  If the rtp proxy test failed (wrong version or not started)
00096  *    retry test from time to time, when some *rtpproxy* function
00097  *    is invoked. Minimum interval between retries can be
00098  *    configured via rtpproxy_disable_tout module parameter (default
00099  *    is 60 seconds). Setting it to -1 will disable periodic
00100  *    rechecks completely, setting it to 0 will force checks
00101  *    for each *rtpproxy* function call. (andrei)
00102  *
00103  * 2004-03-22  Fix assignment of rtpproxy_retr and rtpproxy_tout module
00104  *    parameters.
00105  *
00106  * 2004-03-22  Fix get_body position (should be called before get_callid)
00107  *             (andrei)
00108  *
00109  * 2004-03-24  Fix newport for null ip address case (e.g onhold re-INVITE)
00110  *             (andrei)
00111  *
00112  * 2004-09-30  added received port != via port test (andrei)
00113  *
00114  * 2004-10-10   force_socket option introduced (jiri)
00115  *
00116  * 2005-02-24  Added support for using more than one rtp proxy, in which
00117  *    case traffic will be distributed evenly among them. In addition,
00118  *    each such proxy can be assigned a weight, which will specify
00119  *    which share of the traffic should be placed to this particular
00120  *    proxy.
00121  *
00122  *    Introduce failover mechanism, so that if SER detects that one
00123  *    of many proxies is no longer available it temporarily decreases
00124  *    its weight to 0, so that no traffic will be assigned to it.
00125  *    Such "disabled" proxies are periodically checked to see if they
00126  *    are back to normal in which case respective weight is restored
00127  *    resulting in traffic being sent to that proxy again.
00128  *
00129  *    Those features can be enabled by specifying more than one "URI"
00130  *    in the rtpproxy_sock parameter, optionally followed by the weight,
00131  *    which if absent is assumed to be 1, for example:
00132  *
00133  *    rtpproxy_sock="unix:/foo/bar=4 udp:1.2.3.4:3456=3 udp:5.6.7.8:5432=1"
00134  *
00135  * 2005-02-25  Force for pinging the socket returned by USRLOC (bogdan)
00136  *
00137  * 2005-03-22  support for multiple media streams added (netch)
00138  *
00139  * 2005-07-11  SIP ping support added (bogdan)
00140  *
00141  * 2005-07-14  SDP origin (o=) IP may be also changed (bogdan)
00142  *
00143  * 2006-03-08  fix_nated_sdp() may take one more param to force a specific IP;
00144  *             force_rtp_proxy() accepts a new flag 's' to swap creation/
00145  *              confirmation between requests/replies; 
00146  *             add_rcv_param() may take as parameter a flag telling if the
00147  *              parameter should go to the contact URI or contact header;
00148  *             (bogdan)
00149  * 2006-03-28 Support for changing session-level SDP connection (c=) IP when
00150  *            media-description also includes connection information (bayan)
00151  * 2007-04-13 Support multiple sets of rtpproxies and set selection added
00152  *            (ancuta)
00153  * 2007-04-26 Added some MI commands:
00154  *             nh_enable_ping used to enable or disable natping
00155  *             nh_enable_rtpp used to enable or disable a specific rtp proxy
00156  *             nh_show_rtpp   used to display information for all rtp proxies 
00157  *             (ancuta)
00158  * 2007-05-09 New function start_recording() allowing to start recording RTP 
00159  *             session in the RTP proxy (Carsten Bock - ported from SER)
00160  * 2007-09-11 Separate timer process and support for multiple timer processes
00161  *             (bogdan)
00162  * 2008-12-12 Support for RTCP attribute in the SDP
00163  *              (Min Wang/BASIS AudioNet - ported from SER)
00164  */
00165 
00166 #include <sys/types.h>
00167 #include <sys/socket.h>
00168 #include <sys/time.h>
00169 #include <netinet/in.h>
00170 #include <netinet/in_systm.h>
00171 #ifndef __USE_BSD
00172 #define  __USE_BSD
00173 #endif
00174 #include <netinet/ip.h>
00175 #ifndef __FAVOR_BSD
00176 #define __FAVOR_BSD
00177 #endif
00178 #include <netinet/udp.h>
00179 #include <arpa/inet.h>
00180 #include <sys/uio.h>
00181 #include <sys/un.h>
00182 #include <ctype.h>
00183 #include <errno.h>
00184 #include <netdb.h>
00185 #include <poll.h>
00186 #include <stdio.h>
00187 #include <stdlib.h>
00188 #include <string.h>
00189 #include <unistd.h>
00190 
00191 #include "../../flags.h"
00192 #include "../../sr_module.h"
00193 #include "../../dprint.h"
00194 #include "../../data_lump.h"
00195 #include "../../data_lump_rpl.h"
00196 #include "../../error.h"
00197 #include "../../forward.h"
00198 #include "../../mem/mem.h"
00199 #include "../../parser/parse_from.h"
00200 #include "../../parser/parse_to.h"
00201 #include "../../parser/parse_uri.h"
00202 #include "../../parser/parser_f.h"
00203 #include "../../resolve.h"
00204 #include "../../timer.h"
00205 #include "../../trim.h"
00206 #include "../../ut.h"
00207 #include "../../mi/attr.h"
00208 #include "../../pvar.h"
00209 #include "../../msg_translator.h"
00210 #include "../../usr_avp.h"
00211 #include "../../socket_info.h"
00212 #include "../../mod_fix.h"
00213 #include "../registrar/sip_msg.h"
00214 #include "../usrloc/usrloc.h"
00215 #include "nathelper.h"
00216 #include "nhelpr_funcs.h"
00217 #include "sip_pinger.h"
00218 #include "rtpproxy_stream.h"
00219  
00220 MODULE_VERSION
00221 
00222 #if !defined(AF_LOCAL)
00223 #define  AF_LOCAL AF_UNIX
00224 #endif
00225 #if !defined(PF_LOCAL)
00226 #define  PF_LOCAL PF_UNIX
00227 #endif
00228 
00229 /* NAT UAC test constants */
00230 #define  NAT_UAC_TEST_C_1918  0x01
00231 #define  NAT_UAC_TEST_RCVD 0x02
00232 #define  NAT_UAC_TEST_V_1918  0x04
00233 #define  NAT_UAC_TEST_S_1918  0x08
00234 #define  NAT_UAC_TEST_RPORT   0x10
00235 
00236 
00237 #define DEFAULT_RTPP_SET_ID      0
00238 
00239 #define MI_SET_NATPING_STATE     "nh_enable_ping"
00240 #define MI_DEFAULT_NATPING_STATE 1
00241 
00242 #define MI_ENABLE_RTP_PROXY         "nh_enable_rtpp"
00243 #define MI_MIN_RECHECK_TICKS     0
00244 #define MI_MAX_RECHECK_TICKS     (unsigned int)-1
00245 
00246 #define MI_SHOW_RTP_PROXIES         "nh_show_rtpp"
00247 
00248 #define MI_RTP_PROXY_NOT_FOUND      "RTP proxy not found"
00249 #define MI_RTP_PROXY_NOT_FOUND_LEN  (sizeof(MI_RTP_PROXY_NOT_FOUND)-1)
00250 #define MI_PING_DISABLED         "NATping disabled from script"
00251 #define MI_PING_DISABLED_LEN     (sizeof(MI_PING_DISABLED)-1)
00252 #define MI_SET                "set"
00253 #define MI_SET_LEN               (sizeof(MI_SET)-1)
00254 #define MI_INDEX              "index"
00255 #define MI_INDEX_LEN          (sizeof(MI_INDEX)-1)
00256 #define MI_DISABLED              "disabled"
00257 #define MI_DISABLED_LEN          (sizeof(MI_DISABLED)-1)
00258 #define MI_WEIGHT             "weight"
00259 #define MI_WEIGHT_LEN            (sizeof(MI_WEIGHT)-1)
00260 #define MI_RECHECK_TICKS         "recheck_ticks"
00261 #define MI_RECHECK_T_LEN         (sizeof(MI_RECHECK_TICKS)-1)
00262 
00263 
00264 
00265 /* Supported version of the RTP proxy command protocol */
00266 #define  SUP_CPROTOVER  20040107
00267 /* Required additional version of the RTP proxy command protocol */
00268 #define  REQ_CPROTOVER  "20050322"
00269 /* Additional version necessary for re-packetization support */
00270 #define  REP_CPROTOVER  "20071116"
00271 #define  PTL_CPROTOVER  "20081102"
00272 
00273 #define  CPORT    "22222"
00274 static int nat_uac_test_f(struct sip_msg* msg, char* str1, char* str2);
00275 static int fix_nated_contact_f(struct sip_msg *, char *, char *);
00276 static int fix_nated_sdp_f(struct sip_msg *, char *, char *);
00277 static int extract_mediaip(str *, str *, int *, char *);
00278 static int extract_mediainfo(str *, str *, str *);
00279 static int extract_rtcp(str *body, str *rtcpport);
00280 static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);
00281 static int alter_mediaport(struct sip_msg *, str *, str *, str *, int);
00282 static int alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport);
00283 static char *gencookie();
00284 static int rtpp_test(struct rtpp_node*, int, int);
00285 static int unforce_rtp_proxy_f(struct sip_msg *, char *, char *);
00286 static int force_rtp_proxy0_f(struct sip_msg *, char *, char *);
00287 static int force_rtp_proxy1_f(struct sip_msg *, char *, char *);
00288 static int force_rtp_proxy2_f(struct sip_msg *, char *, char *);
00289 static int force_rtp_proxy(struct sip_msg *, char *, char *, int);
00290 static int fix_nated_register_f(struct sip_msg *, char *, char *);
00291 static int fixup_fix_nated_register(void** param, int param_no);
00292 static int fixup_fix_sdp(void** param, int param_no);
00293 static int add_rcv_param_f(struct sip_msg *, char *, char *);
00294 static int start_recording_f(struct sip_msg *, char *, char *);
00295 static int rtpproxy_answer1_f(struct sip_msg *, char *, char *);
00296 static int rtpproxy_answer2_f(struct sip_msg *, char *, char *);
00297 static int rtpproxy_offer1_f(struct sip_msg *, char *, char *);
00298 static int rtpproxy_offer2_f(struct sip_msg *, char *, char *);
00299 
00300 static char *find_sdp_line(char *, char *, char);
00301 static char *find_next_sdp_line(char *, char *, char, char *);
00302 
00303 static int add_rtpproxy_socks(struct rtpp_set * rtpp_list, char * rtpproxy);
00304 static int fixup_set_id(void ** param, int param_no);
00305 static int set_rtp_proxy_set_f(struct sip_msg * msg, char * str1, char * str2);
00306 static struct rtpp_set * select_rtpp_set(int id_set);
00307 
00308 static int rtpproxy_set_store(modparam_t type, void * val);
00309 static int nathelper_add_rtpproxy_set( char * rtp_proxies);
00310 
00311 static void nh_timer(unsigned int, void *);
00312 static int mod_init(void);
00313 static int child_init(int);
00314 static void mod_destroy(void);
00315 
00316 /*mi commands*/
00317 static struct mi_root* mi_enable_natping(struct mi_root* cmd_tree,
00318       void* param );
00319 static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
00320       void* param );
00321 static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
00322       void* param);
00323 
00324 
00325 static usrloc_api_t ul;
00326 
00327 static int cblen = 0;
00328 static int natping_interval = 0;
00329 struct socket_info* force_socket = 0;
00330 
00331 
00332 static struct {
00333    const char *cnetaddr;
00334    uint32_t netaddr;
00335    uint32_t mask;
00336 } nets_1918[] = {
00337    {"10.0.0.0",    0, 0xffffffffu << 24},
00338    {"172.16.0.0",  0, 0xffffffffu << 20},
00339    {"192.168.0.0", 0, 0xffffffffu << 16},
00340    {NULL, 0, 0}
00341 };
00342 
00343 static struct {
00344    const char *s;
00345    int len;
00346    int is_rtp;
00347 } sup_ptypes[] = {
00348    {.s = "udp",       .len = 3, .is_rtp = 0},
00349    {.s = "udptl",     .len = 5, .is_rtp = 0},
00350    {.s = "rtp/avp",   .len = 7, .is_rtp = 1},
00351    {.s = "rtp/avpf",  .len = 8, .is_rtp = 1},
00352    {.s = "rtp/savp",  .len = 8, .is_rtp = 1},
00353    {.s = "rtp/savpf", .len = 9, .is_rtp = 1},
00354    {.s = "udp/bfcp",  .len = 8, .is_rtp = 0},
00355    {.s = NULL,        .len = 0, .is_rtp = 0}
00356 };
00357 
00358 /*
00359  * If this parameter is set then the natpinger will ping only contacts
00360  * that have the NAT flag set in user location database
00361  */
00362 static int ping_nated_only = 0;
00363 static const char sbuf[4] = {0, 0, 0, 0};
00364 static char *force_socket_str = 0;
00365 static int rtpproxy_disable_tout = 60;
00366 static int rtpproxy_retr = 5;
00367 static int rtpproxy_tout = 1;
00368 static pid_t mypid;
00369 static unsigned int myseqn = 0;
00370 static str nortpproxy_str = str_init("a=nortpproxy:yes");
00371 static int sipping_flag = -1;
00372 static int natping_processes = 1;
00373 
00374 static char* rcv_avp_param = NULL;
00375 static unsigned short rcv_avp_type = 0;
00376 static int_str rcv_avp_name;
00377 
00378 static char *natping_socket = 0;
00379 static int raw_sock = -1;
00380 static unsigned int raw_ip = 0;
00381 static unsigned short raw_port = 0;
00382 
00383 
00384 static char ** rtpp_strings=0;
00385 static int rtpp_sets=0; /*used in rtpproxy_set_store()*/
00386 static int rtpp_set_count = 0;
00387 static unsigned int current_msg_id = (unsigned int)-1;
00388 /* RTP proxy balancing list */
00389 struct rtpp_set_head * rtpp_set_list =0;
00390 struct rtpp_set * selected_rtpp_set =0;
00391 struct rtpp_set * default_rtpp_set=0;
00392 
00393 /* array with the sockets used by rtpporxy (per process)*/
00394 static unsigned int rtpp_no = 0;
00395 static int *rtpp_socks = 0;
00396 
00397 
00398 /*0-> disabled, 1 ->enabled*/
00399 unsigned int *natping_state=0;
00400 
00401 static cmd_export_t cmds[] = {
00402    {"fix_nated_contact",  (cmd_function)fix_nated_contact_f,    0,
00403       0, 0,
00404       REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00405    {"fix_nated_sdp",      (cmd_function)fix_nated_sdp_f,        1,
00406       fixup_fix_sdp,  0,
00407       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00408    {"fix_nated_sdp",      (cmd_function)fix_nated_sdp_f,        2,
00409       fixup_fix_sdp, 0,
00410       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00411    {"set_rtp_proxy_set",  (cmd_function)set_rtp_proxy_set_f,    1,
00412       fixup_set_id, 0,
00413       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00414    {"unforce_rtp_proxy",  (cmd_function)unforce_rtp_proxy_f,    0,
00415       0, 0,
00416       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00417    {"force_rtp_proxy",    (cmd_function)force_rtp_proxy0_f,     0,
00418       0, 0,
00419       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00420    {"force_rtp_proxy",    (cmd_function)force_rtp_proxy1_f,     1,
00421       0, 0,
00422       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00423    {"force_rtp_proxy",    (cmd_function)force_rtp_proxy2_f,     2,
00424       0, 0,
00425       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00426    {"nat_uac_test",       (cmd_function)nat_uac_test_f,         1,
00427       fixup_uint_null, 0,
00428       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00429    {"fix_nated_register", (cmd_function)fix_nated_register_f,   0,
00430       fixup_fix_nated_register, 0,
00431       REQUEST_ROUTE },
00432    {"add_rcv_param",      (cmd_function)add_rcv_param_f,        0,
00433       0, 0,
00434       REQUEST_ROUTE },
00435    {"add_rcv_param",      (cmd_function)add_rcv_param_f,        1,
00436       fixup_uint_null, 0,
00437       REQUEST_ROUTE },
00438    {"start_recording",    (cmd_function)start_recording_f,      0,
00439       0, 0,
00440       REQUEST_ROUTE | ONREPLY_ROUTE },
00441    {"rtpproxy_offer",   (cmd_function)rtpproxy_offer1_f,     0,
00442       0, 0,
00443       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00444    {"rtpproxy_offer",   (cmd_function)rtpproxy_offer1_f,     1,
00445       0, 0,
00446       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00447    {"rtpproxy_offer",   (cmd_function)rtpproxy_offer2_f,     2,
00448       0, 0,
00449       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00450    {"rtpproxy_answer",  (cmd_function)rtpproxy_answer1_f,    0,
00451       0, 0,
00452       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00453    {"rtpproxy_answer",  (cmd_function)rtpproxy_answer1_f,    1,
00454       0, 0,
00455       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00456    {"rtpproxy_answer",  (cmd_function)rtpproxy_answer2_f,    2,
00457       0, 0,
00458       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00459    {"rtpproxy_stream2uac",(cmd_function)rtpproxy_stream2uac2_f, 2,
00460       fixup_var_str_int, 0,
00461       REQUEST_ROUTE | ONREPLY_ROUTE },
00462    {"rtpproxy_stream2uas",(cmd_function)rtpproxy_stream2uas2_f, 2,
00463       fixup_var_str_int, 0,
00464       REQUEST_ROUTE | ONREPLY_ROUTE },
00465    {"rtpproxy_stop_stream2uac",(cmd_function)rtpproxy_stop_stream2uac2_f,0,
00466       NULL, 0,
00467       REQUEST_ROUTE | ONREPLY_ROUTE },
00468    {"rtpproxy_stop_stream2uas",(cmd_function)rtpproxy_stop_stream2uas2_f,0,
00469       NULL, 0,
00470       REQUEST_ROUTE | ONREPLY_ROUTE },
00471    {0, 0, 0, 0, 0, 0}
00472 };
00473 
00474 static param_export_t params[] = {
00475    {"natping_interval",      INT_PARAM, &natping_interval      },
00476    {"ping_nated_only",       INT_PARAM, &ping_nated_only       },
00477    {"nortpproxy_str",        STR_PARAM, &nortpproxy_str.s      },
00478    {"rtpproxy_sock",         STR_PARAM|USE_FUNC_PARAM,
00479                             (void*)rtpproxy_set_store          },
00480    {"rtpproxy_disable_tout", INT_PARAM, &rtpproxy_disable_tout },
00481    {"rtpproxy_retr",         INT_PARAM, &rtpproxy_retr         },
00482    {"rtpproxy_tout",         INT_PARAM, &rtpproxy_tout         },
00483    {"received_avp",          STR_PARAM, &rcv_avp_param         },
00484    {"force_socket",          STR_PARAM, &force_socket_str      },
00485    {"sipping_from",          STR_PARAM, &sipping_from.s        },
00486    {"sipping_method",        STR_PARAM, &sipping_method.s      },
00487    {"sipping_bflag",         INT_PARAM, &sipping_flag          },
00488    {"natping_processes",     INT_PARAM, &natping_processes     },
00489    {"natping_socket",        STR_PARAM, &natping_socket        },
00490    {0, 0, 0}
00491 };
00492 
00493 static mi_export_t mi_cmds[] = {
00494    {MI_SET_NATPING_STATE,    mi_enable_natping,    0,                0, 0},
00495    {MI_ENABLE_RTP_PROXY,     mi_enable_rtp_proxy,  0,                0, 0},
00496    {MI_SHOW_RTP_PROXIES,     mi_show_rtpproxies,   MI_NO_INPUT_FLAG, 0, 0},
00497    { 0, 0, 0, 0, 0}
00498 };
00499 
00500 
00501 struct module_exports exports = {
00502    "nathelper",
00503    DEFAULT_DLFLAGS, /* dlopen flags */
00504    cmds,
00505    params,
00506    0,           /* exported statistics */
00507    mi_cmds,     /* exported MI functions */
00508    0,           /* exported pseudo-variables */
00509    0,           /* extra processes */
00510    mod_init,
00511    0,           /* reply processing */
00512    mod_destroy, /* destroy function */
00513    child_init
00514 };
00515 
00516 
00517 static int rtpproxy_set_store(modparam_t type, void * val){
00518 
00519    char * p;
00520    int len;
00521 
00522    p = (char* )val;
00523 
00524    if(p==0 || *p=='\0'){
00525       return 0;
00526    }
00527 
00528    if(rtpp_sets==0){
00529       rtpp_strings = (char**)pkg_malloc(sizeof(char*));
00530       if(!rtpp_strings){
00531          LM_ERR("no pkg memory left\n");
00532          return -1;
00533       }
00534    } else {/*realloc to make room for the current set*/
00535       rtpp_strings = (char**)pkg_realloc(rtpp_strings, 
00536                                 (rtpp_sets+1)* sizeof(char*));
00537       if(!rtpp_strings){
00538          LM_ERR("no pkg memory left\n");
00539          return -1;
00540       }
00541    }
00542    
00543    /*allocate for the current set of urls*/
00544    len = strlen(p);
00545    rtpp_strings[rtpp_sets] = (char*)pkg_malloc((len+1)*sizeof(char));
00546 
00547    if(!rtpp_strings[rtpp_sets]){
00548       LM_ERR("no pkg memory left\n");
00549       return -1;
00550    }
00551    
00552    memcpy(rtpp_strings[rtpp_sets], p, len);
00553    rtpp_strings[rtpp_sets][len] = '\0';
00554    rtpp_sets++;
00555 
00556    return 0;
00557 }
00558 
00559 
00560 static int add_rtpproxy_socks(struct rtpp_set * rtpp_list, 
00561                               char * rtpproxy){
00562    /* Make rtp proxies list. */
00563    char *p, *p1, *p2, *plim;
00564    struct rtpp_node *pnode;
00565    int weight;
00566 
00567    p = rtpproxy;
00568    plim = p + strlen(p);
00569 
00570    for(;;) {
00571          weight = 1;
00572       while (*p && isspace((int)*p))
00573          ++p;
00574       if (p >= plim)
00575          break;
00576       p1 = p;
00577       while (*p && !isspace((int)*p))
00578          ++p;
00579       if (p <= p1)
00580          break; /* may happen??? */
00581       /* Have weight specified? If yes, scan it */
00582       p2 = memchr(p1, '=', p - p1);
00583       if (p2 != NULL) {
00584          weight = strtoul(p2 + 1, NULL, 10);
00585       } else {
00586          p2 = p;
00587       }
00588       pnode = shm_malloc(sizeof(struct rtpp_node));
00589       if (pnode == NULL) {
00590          LM_ERR("no shm memory left\n");
00591          return -1;
00592       }
00593       memset(pnode, 0, sizeof(*pnode));
00594       pnode->idx = rtpp_no++;
00595       pnode->rn_recheck_ticks = 0;
00596       pnode->rn_weight = weight;
00597       pnode->rn_umode = 0;
00598       pnode->rn_disabled = 0;
00599       pnode->rn_url.s = shm_malloc(p2 - p1 + 1);
00600       if (pnode->rn_url.s == NULL) {
00601          shm_free(pnode);
00602          LM_ERR("no shm memory left\n");
00603          return -1;
00604       }
00605       memmove(pnode->rn_url.s, p1, p2 - p1);
00606       pnode->rn_url.s[p2 - p1]   = 0;
00607       pnode->rn_url.len          = p2-p1;
00608 
00609       LM_DBG("url is %s, len is %i\n", pnode->rn_url.s, pnode->rn_url.len);
00610       /* Leave only address in rn_address */
00611       pnode->rn_address = pnode->rn_url.s;
00612       if (strncasecmp(pnode->rn_address, "udp:", 4) == 0) {
00613          pnode->rn_umode = 1;
00614          pnode->rn_address += 4;
00615       } else if (strncasecmp(pnode->rn_address, "udp6:", 5) == 0) {
00616          pnode->rn_umode = 6;
00617          pnode->rn_address += 5;
00618       } else if (strncasecmp(pnode->rn_address, "unix:", 5) == 0) {
00619          pnode->rn_umode = 0;
00620          pnode->rn_address += 5;
00621       }
00622 
00623       if (rtpp_list->rn_first == NULL) {
00624          rtpp_list->rn_first = pnode;
00625       } else {
00626          rtpp_list->rn_last->rn_next = pnode;
00627       }
00628 
00629       rtpp_list->rn_last = pnode;
00630       rtpp_list->rtpp_node_count++;
00631    }
00632    return 0;
00633 }
00634 
00635 
00636 /* 0-succes
00637  *  -1 - erorr
00638  * */
00639 static int nathelper_add_rtpproxy_set( char * rtp_proxies)
00640 {
00641    char *p,*p2;
00642    struct rtpp_set * rtpp_list;
00643    unsigned int my_current_id;
00644    str id_set;
00645    int new_list;
00646 
00647    /* empty definition? */
00648    p= rtp_proxies;
00649    if(!p || *p=='\0'){
00650       return 0;
00651    }
00652 
00653    for(;*p && isspace(*p);p++);
00654    if(*p=='\0'){
00655       return 0;
00656    }
00657 
00658    rtp_proxies = strstr(p, "==");
00659    if(rtp_proxies){
00660       if(*(rtp_proxies +2)=='\0'){
00661          LM_ERR("script error -invalid rtp proxy list!\n");
00662          return -1;
00663       }
00664          
00665       *rtp_proxies = '\0';
00666       p2 = rtp_proxies-1;
00667       for(;isspace(*p2); *p2 = '\0',p2--);
00668       id_set.s = p;  id_set.len = p2 - p+1;
00669          
00670       if(id_set.len <= 0 ||str2int(&id_set, &my_current_id)<0 ){
00671       LM_ERR("script error -invalid set_id value!\n");
00672          return -1;
00673       }
00674          
00675       rtp_proxies+=2;
00676    }else{
00677       rtp_proxies = p;
00678       my_current_id = DEFAULT_RTPP_SET_ID;
00679    }
00680 
00681    for(;*rtp_proxies && isspace(*rtp_proxies);rtp_proxies++);
00682 
00683    if(!(*rtp_proxies)){
00684       LM_ERR("script error -empty rtp_proxy list\n");
00685       return -1;;
00686    }
00687 
00688    /*search for the current_id*/
00689    rtpp_list = rtpp_set_list ? rtpp_set_list->rset_first : 0;
00690    while( rtpp_list != 0 && rtpp_list->id_set!=my_current_id)
00691       rtpp_list = rtpp_list->rset_next;
00692 
00693    if(rtpp_list==NULL){ /*if a new id_set : add a new set of rtpp*/
00694       rtpp_list = shm_malloc(sizeof(struct rtpp_set));
00695       if(!rtpp_list){
00696          LM_ERR("no shm memory left\n");
00697          return -1;
00698       }
00699       memset(rtpp_list, 0, sizeof(struct rtpp_set));
00700       rtpp_list->id_set = my_current_id;
00701       new_list = 1;
00702    } else {
00703       new_list = 0;
00704    }
00705 
00706    if(add_rtpproxy_socks(rtpp_list, rtp_proxies)!= 0){
00707       /*if this list will not be inserted, clean it up*/
00708       goto error;
00709    }
00710 
00711    if (new_list) {
00712       if(!rtpp_set_list){/*initialize the list of set*/
00713          rtpp_set_list = shm_malloc(sizeof(struct rtpp_set_head));
00714          if(!rtpp_set_list){
00715             LM_ERR("no shm memory left\n");
00716             return -1;
00717          }
00718          memset(rtpp_set_list, 0, sizeof(struct rtpp_set_head));
00719       }
00720 
00721       /*update the list of set info*/
00722       if(!rtpp_set_list->rset_first){
00723          rtpp_set_list->rset_first = rtpp_list;
00724       }else{
00725          rtpp_set_list->rset_last->rset_next = rtpp_list;
00726       }
00727 
00728       rtpp_set_list->rset_last = rtpp_list;
00729       rtpp_set_count++;
00730 
00731       if(my_current_id == DEFAULT_RTPP_SET_ID){
00732          default_rtpp_set = rtpp_list;
00733       }
00734    }
00735 
00736    return 0;
00737 error:
00738    return -1;
00739 }
00740 
00741 
00742 static int fixup_set_id(void ** param, int param_no)
00743 {
00744    int int_val, err;
00745    struct rtpp_set* rtpp_list;
00746 
00747    int_val = str2s(*param, strlen(*param), &err);
00748    if (err == 0) {
00749       pkg_free(*param);
00750       if((rtpp_list = select_rtpp_set(int_val)) ==0){
00751          LM_ERR("rtpp_proxy set %i not configured\n", int_val);
00752          return E_CFG;
00753       }
00754       *param = (void *)rtpp_list;
00755    
00756       return 0;
00757    } else {
00758       LM_ERR("bad number <%s>\n",   (char *)(*param));
00759       return E_CFG;
00760    }
00761 }
00762 
00763 static int
00764 fixup_fix_sdp(void** param, int param_no)
00765 {
00766    pv_elem_t *model;
00767    str s;
00768 
00769    if (param_no==1) {
00770       /* flags */
00771       return fixup_uint_null( param, param_no);
00772    }
00773    /* new IP */
00774    model=NULL;
00775    s.s = (char*)(*param); s.len = strlen(s.s);
00776    if(pv_parse_format(&s,&model)<0) {
00777       LM_ERR("wrong format[%s]!\n", (char*)(*param));
00778       return E_UNSPEC;
00779    }
00780    if (model==NULL) {
00781       LM_ERR("empty parameter!\n");
00782       return E_UNSPEC;
00783    }
00784    *param = (void*)model;
00785    return 0;
00786 }
00787 
00788 static int fixup_fix_nated_register(void** param, int param_no)
00789 {
00790    if (rcv_avp_name.n == 0) {
00791       LM_ERR("you must set 'received_avp' parameter. Must be same value as"
00792             " parameter 'received_avp' of registrar module\n");
00793       return -1;
00794    }
00795    return 0;
00796 }
00797 
00798 static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree, 
00799                                     void* param )
00800 {  struct mi_node* node;
00801    str rtpp_url;
00802    unsigned int enable;
00803    struct rtpp_set * rtpp_list;
00804    struct rtpp_node * crt_rtpp;
00805    int found;
00806 
00807    found = 0;
00808 
00809    if(rtpp_set_list ==NULL)
00810       goto end;
00811 
00812    node = cmd_tree->node.kids;
00813    if(node == NULL)
00814       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00815 
00816    if(node->value.s == NULL || node->value.len ==0)
00817       return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00818 
00819    rtpp_url = node->value;
00820 
00821    node = node->next;
00822    if(node == NULL)
00823       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00824 
00825    enable = 0;
00826    if( strno2int( &node->value, &enable) <0)
00827       goto error;
00828 
00829    for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL; 
00830                rtpp_list = rtpp_list->rset_next){
00831 
00832       for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
00833                   crt_rtpp = crt_rtpp->rn_next){
00834          /*found a matching rtpp*/
00835          
00836          if(crt_rtpp->rn_url.len == rtpp_url.len){
00837             
00838             if(strncmp(crt_rtpp->rn_url.s, rtpp_url.s, rtpp_url.len) == 0){
00839                /*set the enabled/disabled status*/
00840                found = 1;
00841                crt_rtpp->rn_recheck_ticks = 
00842                   enable? MI_MIN_RECHECK_TICKS : MI_MAX_RECHECK_TICKS;
00843                crt_rtpp->rn_disabled = enable?0:1;
00844             }
00845          }
00846       }
00847    }
00848 
00849 end:
00850    if(found)
00851       return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00852    return init_mi_tree(404,MI_RTP_PROXY_NOT_FOUND,MI_RTP_PROXY_NOT_FOUND_LEN);
00853 error:
00854    return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00855 }
00856 
00857 
00858 
00859 static struct mi_root* mi_enable_natping(struct mi_root* cmd_tree, 
00860                                  void* param )
00861 {
00862    unsigned int value;
00863    struct mi_node* node;
00864 
00865    if (natping_state==NULL)
00866       return init_mi_tree( 400, MI_PING_DISABLED, MI_PING_DISABLED_LEN);
00867 
00868    node = cmd_tree->node.kids;
00869    if(node == NULL)
00870       return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00871 
00872    value = 0;
00873    if( strno2int( &node->value, &value) <0)
00874       goto error;
00875 
00876    (*natping_state) = value?1:0;
00877    
00878    return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00879 error:
00880    return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00881 }
00882 
00883 
00884 
00885 #define add_rtpp_node_int_info(_parent, _name, _name_len, _value, _child,\
00886                         _len, _string, _error)\
00887    do {\
00888       (_string) = int2str((_value), &(_len));\
00889       if((_string) == 0){\
00890          LM_ERR("cannot convert int value\n");\
00891             goto _error;\
00892       }\
00893       if(((_child) = add_mi_node_child((_parent), MI_DUP_VALUE, (_name), \
00894             (_name_len), (_string), (_len))   ) == 0)\
00895          goto _error;\
00896    }while(0);
00897 
00898 static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree, 
00899                                     void* param)
00900 {
00901    struct mi_node* node, *crt_node, *child;
00902    struct mi_root* root;
00903    struct mi_attr * attr;
00904    struct rtpp_set * rtpp_list;
00905    struct rtpp_node * crt_rtpp;
00906    char * string, *id;
00907    int id_len, len;
00908 
00909    string = id = 0;
00910 
00911    root = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00912    if (!root) {
00913       LM_ERR("the MI tree cannot be initialized!\n");
00914       return 0;
00915    }
00916 
00917    if(rtpp_set_list ==NULL)
00918       return root;
00919 
00920    node = &root->node;
00921 
00922    for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL; 
00923                rtpp_list = rtpp_list->rset_next){
00924 
00925       for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
00926                   crt_rtpp = crt_rtpp->rn_next){
00927 
00928          id =  int2str(rtpp_list->id_set, &id_len);
00929          if(!id){
00930             LM_ERR("cannot convert set id\n");
00931             goto error;
00932          }
00933 
00934          if(!(crt_node = add_mi_node_child(node, 0, crt_rtpp->rn_url.s, 
00935                crt_rtpp->rn_url.len, 0,0)) ) {
00936             LM_ERR("cannot add the child node to the tree\n");
00937             goto error;
00938          }
00939 
00940          LM_DBG("adding node name %s \n",crt_rtpp->rn_url.s );
00941 
00942          if((attr = add_mi_attr(crt_node, MI_DUP_VALUE, MI_SET, MI_SET_LEN, 
00943                            id, id_len))== 0){
00944             LM_ERR("cannot add attributes to the node\n");
00945             goto error;
00946          }
00947 
00948          add_rtpp_node_int_info(crt_node, MI_INDEX, MI_INDEX_LEN,
00949             crt_rtpp->idx, child, len,string,error);
00950          add_rtpp_node_int_info(crt_node, MI_DISABLED, MI_DISABLED_LEN,
00951             crt_rtpp->rn_disabled, child, len,string,error);
00952          add_rtpp_node_int_info(crt_node, MI_WEIGHT, MI_WEIGHT_LEN,
00953             crt_rtpp->rn_weight,  child, len, string,error);
00954          add_rtpp_node_int_info(crt_node, MI_RECHECK_TICKS,MI_RECHECK_T_LEN,
00955             crt_rtpp->rn_recheck_ticks, child, len, string, error);
00956       }
00957    }
00958 
00959    return root;
00960 error:
00961    if (root)
00962       free_mi_tree(root);
00963    return 0;
00964 }
00965 
00966 
00967 static int init_raw_socket(void)
00968 {
00969    int on = 1;
00970 
00971    raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
00972    if (raw_sock ==-1) {
00973       LM_ERR("cannot create raw socket\n");
00974       return -1;
00975    }
00976 
00977    if (setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
00978       LM_ERR("cannot set socket options\n");
00979       return -1;
00980    }
00981 
00982    return raw_sock;
00983 }
00984 
00985 
00986 static int get_natping_socket(char *socket, 
00987                               unsigned int *ip, unsigned short *port)
00988 {
00989    struct hostent* he;
00990    str host;
00991    int lport;
00992    int lproto;
00993 
00994    if (parse_phostport( socket, strlen(socket), &host.s, &host.len,
00995    &lport, &lproto)!=0){
00996       LM_CRIT("invalid natping_socket parameter <%s>\n",natping_socket);
00997       return -1;
00998    }
00999 
01000    if (lproto!=PROTO_UDP && lproto!=PROTO_NONE) {
01001       LM_CRIT("natping_socket can be only UDP <%s>\n",natping_socket);
01002       return 0;
01003    }
01004    lproto = PROTO_UDP;
01005    *port = lport?(unsigned short)lport:SIP_PORT;
01006 
01007    he = sip_resolvehost( &host, port, (unsigned short*)(void*)&lproto, 0, 0);
01008    if (he==0) {
01009       LM_ERR("could not resolve hostname:\"%.*s\"\n", host.len, host.s);
01010       return -1;
01011    }
01012    if (he->h_addrtype != AF_INET) {
01013       LM_ERR("only ipv4 addresses allowed in natping_socket\n");
01014       return -1;
01015    }
01016 
01017    memcpy( ip, he->h_addr_list[0], he->h_length);
01018 
01019    return 0;
01020 }
01021 
01022 
01023 static int
01024 mod_init(void)
01025 {
01026    int i;
01027    bind_usrloc_t bind_usrloc;
01028    struct in_addr addr;
01029    str socket_str;
01030    pv_spec_t avp_spec;
01031    str s;
01032 
01033    if (rcv_avp_param && *rcv_avp_param) {
01034       s.s = rcv_avp_param; s.len = strlen(s.s);
01035       if (pv_parse_spec(&s, &avp_spec)==0
01036             || avp_spec.type!=PVT_AVP) {
01037          LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
01038          return -1;
01039       }
01040 
01041       if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)!=0)
01042       {
01043          LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
01044          return -1;
01045       }
01046    } else {
01047       rcv_avp_name.n = 0;
01048       rcv_avp_type = 0;
01049    }
01050 
01051    if (force_socket_str) {
01052       socket_str.s=force_socket_str;
01053       socket_str.len=strlen(socket_str.s);
01054       force_socket=grep_sock_info(&socket_str,0,0);
01055    }
01056 
01057    /* create raw socket? */
01058    if (natping_socket && natping_socket[0]) {
01059       if (get_natping_socket( natping_socket, &raw_ip, &raw_port)!=0)
01060          return -1;
01061       if (init_raw_socket() < 0)
01062          return -1;
01063    }
01064 
01065    /* any rtpproxy configured? */
01066    if(rtpp_set_list)
01067       default_rtpp_set = select_rtpp_set(DEFAULT_RTPP_SET_ID);
01068 
01069    if (nortpproxy_str.s==NULL || nortpproxy_str.s[0]==0) {
01070       nortpproxy_str.len = 0;
01071       nortpproxy_str.s = NULL;
01072    } else {
01073       nortpproxy_str.len = strlen(nortpproxy_str.s);
01074       while (nortpproxy_str.len > 0 && (nortpproxy_str.s[nortpproxy_str.len - 1] == '\r' ||
01075           nortpproxy_str.s[nortpproxy_str.len - 1] == '\n'))
01076          nortpproxy_str.len--;
01077       if (nortpproxy_str.len == 0)
01078          nortpproxy_str.s = NULL;
01079    }
01080 
01081    if (natping_interval > 0) {
01082       bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
01083       if (!bind_usrloc) {
01084          LM_ERR("can't find usrloc module\n");
01085          return -1;
01086       }
01087 
01088       if (bind_usrloc(&ul) < 0) {
01089          return -1;
01090       }
01091 
01092       natping_state =(unsigned int *) shm_malloc(sizeof(unsigned int));
01093       if (!natping_state) {
01094          LM_ERR("no shmem left\n");
01095          return -1;
01096       }
01097       *natping_state = MI_DEFAULT_NATPING_STATE;
01098 
01099       if (ping_nated_only && ul.nat_flag==0) {
01100          LM_ERR("bad config - ping_nated_only enabled, but no nat bflag"
01101             " set in usrloc module\n");
01102          return -1;
01103       }
01104       if (natping_processes>=8) {
01105          LM_ERR("too many natping processes (%d) max=8\n",
01106             natping_processes);
01107          return -1;
01108       }
01109 
01110       sipping_flag = (sipping_flag==-1)?0:(1<<sipping_flag);
01111 
01112       /* set reply function if SIP natping is enabled */
01113       if (sipping_flag) {
01114          if (sipping_from.s==0 || sipping_from.s[0]==0) {
01115             LM_ERR("SIP ping enabled, but SIP ping FROM is empty!\n");
01116             return -1;
01117          }
01118          if (sipping_method.s==0 || sipping_method.s[0]==0) {
01119             LM_ERR("SIP ping enabled, but SIP ping method is empty!\n");
01120             return -1;
01121          }
01122          sipping_method.len = strlen(sipping_method.s);
01123          sipping_from.len = strlen(sipping_from.s);
01124          exports.response_f = sipping_rpl_filter;
01125          init_sip_ping();
01126       }
01127 
01128       for( i=0 ; i<natping_processes ; i++ ) {
01129          if (register_timer_process( nh_timer, (void*)(unsigned long)i, 1,
01130          TIMER_PROC_INIT_FLAG)<0) {
01131             LM_ERR("failed to register timer routine as process\n");
01132             return -1;
01133          }
01134       }
01135    }
01136 
01137    /* Prepare 1918 networks list */
01138    for (i = 0; nets_1918[i].cnetaddr != NULL; i++) {
01139       if (inet_aton(nets_1918[i].cnetaddr, &addr) != 1)
01140          abort();
01141       nets_1918[i].netaddr = ntohl(addr.s_addr) & nets_1918[i].mask;
01142    }
01143 
01144    /* storing the list of rtp proxy sets in shared memory*/
01145    for(i=0;i<rtpp_sets;i++){
01146       if(nathelper_add_rtpproxy_set(rtpp_strings[i]) !=0){
01147          for(;i<rtpp_sets;i++)
01148             if(rtpp_strings[i])
01149                pkg_free(rtpp_strings[i]);
01150          pkg_free(rtpp_strings);
01151          return -1;
01152       }
01153       if(rtpp_strings[i])
01154          pkg_free(rtpp_strings[i]);
01155    }
01156    if (rtpp_strings)
01157       pkg_free(rtpp_strings);
01158 
01159    return 0;
01160 }
01161 
01162 
01163 static int
01164 child_init(int rank)
01165 {
01166    int n;
01167    char *cp;
01168    struct addrinfo hints, *res;
01169    struct rtpp_set  *rtpp_list;
01170    struct rtpp_node *pnode;
01171 
01172    if (rank<=0 && rank!=PROC_TIMER)
01173       return 0;
01174 
01175    if(rtpp_set_list==NULL )
01176       return 0;
01177 
01178    /* Iterate known RTP proxies - create sockets */
01179    mypid = getpid();
01180 
01181    rtpp_socks = (int*)pkg_malloc( sizeof(int)*rtpp_no );
01182    if (rtpp_socks==NULL) {
01183       LM_ERR("no more pkg memory\n");
01184       return -1;
01185    }
01186 
01187    for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != 0;
01188       rtpp_list = rtpp_list->rset_next){
01189 
01190       for (pnode=rtpp_list->rn_first; pnode!=0; pnode = pnode->rn_next){
01191          char *hostname;
01192 
01193          if (pnode->rn_umode == 0) {
01194             rtpp_socks[pnode->idx] = -1;
01195             goto rptest;
01196          }
01197 
01198          /*
01199           * This is UDP or UDP6. Detect host and port; lookup host;
01200           * do connect() in order to specify peer address
01201           */
01202          hostname = (char*)pkg_malloc(sizeof(char) * (strlen(pnode->rn_address) + 1));
01203          if (hostname==NULL) {
01204             LM_ERR("no more pkg memory\n");
01205             return -1;
01206          }
01207          strcpy(hostname, pnode->rn_address);
01208 
01209          cp = strrchr(hostname, ':');
01210          if (cp != NULL) {
01211             *cp = '\0';
01212             cp++;
01213          }
01214          if (cp == NULL || *cp == '\0')
01215             cp = CPORT;
01216 
01217          memset(&hints, 0, sizeof(hints));
01218          hints.ai_flags = 0;
01219          hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET;
01220          hints.ai_socktype = SOCK_DGRAM;
01221          if ((n = getaddrinfo(hostname, cp, &hints, &res)) != 0) {
01222             LM_ERR("%s\n", gai_strerror(n));
01223             pkg_free(hostname);
01224             return -1;
01225          }
01226          pkg_free(hostname);
01227 
01228          rtpp_socks[pnode->idx] = socket((pnode->rn_umode == 6)
01229              ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
01230          if ( rtpp_socks[pnode->idx] == -1) {
01231             LM_ERR("can't create socket\n");
01232             freeaddrinfo(res);
01233             return -1;
01234          }
01235 
01236          if (connect( rtpp_socks[pnode->idx], res->ai_addr, res->ai_addrlen) == -1) {
01237             LM_ERR("can't connect to a RTP proxy\n");
01238             close( rtpp_socks[pnode->idx] );
01239             rtpp_socks[pnode->idx] = -1;
01240             freeaddrinfo(res);
01241             return -1;
01242          }
01243          freeaddrinfo(res);
01244 rptest:
01245          pnode->rn_disabled = rtpp_test(pnode, 0, 1);
01246       }
01247    }
01248 
01249    return 0;
01250 }
01251 
01252 
01253 static void mod_destroy(void)
01254 {
01255    struct rtpp_set * crt_list, * last_list;
01256    struct rtpp_node * crt_rtpp, *last_rtpp;
01257 
01258    /*free the shared memory*/
01259    if (natping_state)
01260       shm_free(natping_state);
01261 
01262    if(rtpp_set_list == NULL)
01263       return;
01264 
01265    for(crt_list = rtpp_set_list->rset_first; crt_list != NULL; ){
01266 
01267       for(crt_rtpp = crt_list->rn_first; crt_rtpp != NULL;  ){
01268 
01269          if(crt_rtpp->rn_url.s)
01270             shm_free(crt_rtpp->rn_url.s);
01271 
01272          last_rtpp = crt_rtpp;
01273          crt_rtpp = last_rtpp->rn_next;
01274          shm_free(last_rtpp);
01275       }
01276 
01277       last_list = crt_list;
01278       crt_list = last_list->rset_next;
01279       shm_free(last_list);
01280    }
01281 
01282    shm_free(rtpp_set_list);
01283 }
01284 
01285 
01286 
01287 static int
01288 isnulladdr(str *sx, int pf)
01289 {
01290    char *cp;
01291 
01292    if (pf == AF_INET6) {
01293       for(cp = sx->s; cp < sx->s + sx->len; cp++)
01294          if (*cp != '0' && *cp != ':')
01295             return 0;
01296       return 1;
01297    }
01298    return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);
01299 }
01300 
01301 /*
01302  * Replaces ip:port pair in the Contact: field with the source address
01303  * of the packet.
01304  */
01305 static int
01306 fix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2)
01307 {
01308    int offset, len, len1;
01309    char *cp, *buf, temp[2];
01310    contact_t *c;
01311    struct lump *anchor;
01312    struct sip_uri uri;
01313    str hostport;
01314 
01315    if (get_contact_uri(msg, &uri, &c) == -1)
01316       return -1;
01317    if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
01318       LM_ERR("you can't call fix_nated_contact twice, "
01319           "check your config!\n");
01320       return -1;
01321    }
01322 
01323    offset = c->uri.s - msg->buf;
01324    anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T);
01325    if (anchor == 0)
01326       return -1;
01327 
01328    hostport = uri.host;
01329    if (uri.port.len > 0)
01330       hostport.len = uri.port.s + uri.port.len - uri.host.s;
01331 
01332    cp = ip_addr2a(&msg->rcv.src_ip);
01333    len = c->uri.len + strlen(cp) + 6 /* :port */ - hostport.len + 1;
01334    buf = pkg_malloc(len);
01335    if (buf == NULL) {
01336       LM_ERR("out of pkg memory\n");
01337       return -1;
01338    }
01339    temp[0] = hostport.s[0];
01340    temp[1] = c->uri.s[c->uri.len];
01341    c->uri.s[c->uri.len] = hostport.s[0] = '\0';
01342    len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->rcv.src_port,
01343        hostport.s + hostport.len);
01344    if (len1 < len)
01345       len = len1;
01346    hostport.s[0] = temp[0];
01347    c->uri.s[c->uri.len] = temp[1];
01348    if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) {
01349       pkg_free(buf);
01350       return -1;
01351    }
01352    c->uri.s = buf;
01353    c->uri.len = len;
01354 
01355    return 1;
01356 }
01357 
01358 
01359 /*
01360  * Test if IP address pointed to by saddr belongs to RFC1918 networks
01361  */
01362 static inline int
01363 is1918addr(str *saddr)
01364 {
01365    struct in_addr addr;
01366    uint32_t netaddr;
01367    int i, rval;
01368    char backup;
01369 
01370    rval = -1;
01371    backup = saddr->s[saddr->len];
01372    saddr->s[saddr->len] = '\0';
01373    if (inet_aton(saddr->s, &addr) != 1)
01374       goto theend;
01375    netaddr = ntohl(addr.s_addr);
01376    for (i = 0; nets_1918[i].cnetaddr != NULL; i++) {
01377       if ((netaddr & nets_1918[i].mask) == nets_1918[i].netaddr) {
01378          rval = 1;
01379          goto theend;
01380       }
01381    }
01382    rval = 0;
01383 
01384 theend:
01385    saddr->s[saddr->len] = backup;
01386    return rval;
01387 }
01388 
01389 /*
01390  * test for occurrence of RFC1918 IP address in Contact HF
01391  */
01392 static int
01393 contact_1918(struct sip_msg* msg)
01394 {
01395    struct sip_uri uri;
01396    contact_t* c;
01397 
01398    if (get_contact_uri(msg, &uri, &c) == -1)
01399       return -1;
01400 
01401    return (is1918addr(&(uri.host)) == 1) ? 1 : 0;
01402 }
01403 
01404 /*
01405  * test for occurrence of RFC1918 IP address in SDP
01406  */
01407 static int
01408 sdp_1918(struct sip_msg* msg)
01409 {
01410    str body, ip;
01411    int pf;
01412 
01413    if (extract_body(msg, &body) == -1) {
01414       LM_ERR("cannot extract body from msg!\n");
01415       return 0;
01416    }
01417    if (extract_mediaip(&body, &ip, &pf,"c=") == -1) {
01418       LM_ERR("can't extract media IP from the SDP\n");
01419       return 0;
01420    }
01421    if (pf != AF_INET || isnulladdr(&ip, pf))
01422       return 0;
01423 
01424    return (is1918addr(&ip) == 1) ? 1 : 0;
01425 }
01426 
01427 /*
01428  * test for occurrence of RFC1918 IP address in top Via
01429  */
01430 static int
01431 via_1918(struct sip_msg* msg)
01432 {
01433 
01434    return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0;
01435 }
01436 
01437 static int
01438 nat_uac_test_f(struct sip_msg* msg, char* str1, char* str2)
01439 {
01440    int tests;
01441 
01442    tests = (int)(long)str1;
01443 
01444    /* return true if any of the NAT-UAC tests holds */
01445 
01446    /* test if the source port is different from the port in Via */
01447    if ((tests & NAT_UAC_TEST_RPORT) &&
01448        (msg->rcv.src_port!=(msg->via1->port?msg->via1->port:SIP_PORT)) ){
01449       return 1;
01450    }
01451    /*
01452     * test if source address of signaling is different from
01453     * address advertised in Via
01454     */
01455    if ((tests & NAT_UAC_TEST_RCVD) && received_test(msg))
01456       return 1;
01457    /*
01458     * test for occurrences of RFC1918 addresses in Contact
01459     * header field
01460     */
01461    if ((tests & NAT_UAC_TEST_C_1918) && (contact_1918(msg)>0))
01462       return 1;
01463    /*
01464     * test for occurrences of RFC1918 addresses in SDP body
01465     */
01466    if ((tests & NAT_UAC_TEST_S_1918) && sdp_1918(msg))
01467       return 1;
01468    /*
01469     * test for occurrences of RFC1918 addresses top Via
01470     */
01471    if ((tests & NAT_UAC_TEST_V_1918) && via_1918(msg))
01472       return 1;
01473 
01474    /* no test succeeded */
01475    return -1;
01476 
01477 }
01478 
01479 #define  ADD_ADIRECTION 0x01
01480 #define  FIX_MEDIP   0x02
01481 #define  ADD_ANORTPPROXY   0x04
01482 #define  FIX_ORGIP   0x08
01483 
01484 #define  ADIRECTION  "a=direction:active"
01485 #define  ADIRECTION_LEN (sizeof(ADIRECTION) - 1)
01486 
01487 #define  AOLDMEDIP   "a=oldmediaip:"
01488 #define  AOLDMEDIP_LEN  (sizeof(AOLDMEDIP) - 1)
01489 
01490 #define  AOLDMEDIP6  "a=oldmediaip6:"
01491 #define  AOLDMEDIP6_LEN (sizeof(AOLDMEDIP6) - 1)
01492 
01493 #define  AOLDMEDPRT  "a=oldmediaport:"
01494 #define  AOLDMEDPRT_LEN (sizeof(AOLDMEDPRT) - 1)
01495 
01496 
01497 static inline int 
01498 replace_sdp_ip(struct sip_msg* msg, str *org_body, char *line, str *ip)
01499 {
01500    str body1, oldip, newip;
01501    str body = *org_body;
01502    unsigned hasreplaced = 0;
01503    int pf, pf1 = 0;
01504    str body2;
01505    char *bodylimit = body.s + body.len;
01506 
01507    /* Iterate all lines and replace ips in them. */
01508    if (!ip) {
01509       newip.s = ip_addr2a(&msg->rcv.src_ip);
01510       newip.len = strlen(newip.s);
01511    } else {
01512       newip = *ip;
01513    }
01514    body1 = body;
01515    for(;;) {
01516       if (extract_mediaip(&body1, &oldip, &pf,line) == -1)
01517          break;
01518       if (pf != AF_INET) {
01519          LM_ERR("not an IPv4 address in '%s' SDP\n",line);
01520             return -1;
01521          }
01522       if (!pf1)
01523          pf1 = pf;
01524       else if (pf != pf1) {
01525          LM_ERR("mismatching address families in '%s' SDP\n",line);
01526          return -1;
01527       }
01528       body2.s = oldip.s + oldip.len;
01529       body2.len = bodylimit - body2.s;
01530       if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf,1) == -1) {
01531          LM_ERR("can't alter '%s' IP\n",line);
01532          return -1;
01533       }
01534       hasreplaced = 1;
01535       body1 = body2;
01536    }
01537    if (!hasreplaced) {
01538       LM_ERR("can't extract '%s' IP from the SDP\n",line);
01539       return -1;
01540    }
01541 
01542    return 0;
01543 }
01544 
01545 static int
01546 fix_nated_sdp_f(struct sip_msg* msg, char* str1, char* str2)
01547 {
01548    str body;
01549    str ip;
01550    int level;
01551    char *buf;
01552    struct lump* anchor;
01553 
01554    level = (int)(long)str1;
01555    if (str2 && pv_printf_s( msg, (pv_elem_p)str2, &ip)!=0)
01556       return -1;
01557 
01558    if (extract_body(msg, &body) == -1) {
01559       LM_ERR("cannot extract body from msg!\n");
01560       return -1;
01561    }
01562 
01563    if (level & (ADD_ADIRECTION | ADD_ANORTPPROXY)) {
01564       msg->msg_flags |= FL_FORCE_ACTIVE;
01565       anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
01566       if (anchor == NULL) {
01567          LM_ERR("anchor_lump failed\n");
01568          return -1;
01569       }
01570       if (level & ADD_ADIRECTION) {
01571          buf = pkg_malloc((ADIRECTION_LEN + CRLF_LEN) * sizeof(char));
01572          if (buf == NULL) {
01573             LM_ERR("out of pkg memory\n");
01574             return -1;
01575          }
01576          memcpy(buf, CRLF, CRLF_LEN);
01577          memcpy(buf + CRLF_LEN, ADIRECTION, ADIRECTION_LEN);
01578          if (insert_new_lump_after(anchor, buf, ADIRECTION_LEN + CRLF_LEN, 0) == NULL) {
01579             LM_ERR("insert_new_lump_after failed\n");
01580             pkg_free(buf);
01581             return -1;
01582          }
01583       }
01584       if ((level & ADD_ANORTPPROXY) && nortpproxy_str.len) {
01585          buf = pkg_malloc((nortpproxy_str.len + CRLF_LEN) * sizeof(char));
01586          if (buf == NULL) {
01587             LM_ERR("out of pkg memory\n");
01588             return -1;
01589          }
01590          memcpy(buf, CRLF, CRLF_LEN);
01591          memcpy(buf + CRLF_LEN, nortpproxy_str.s, nortpproxy_str.len);
01592          if (insert_new_lump_after(anchor, buf, nortpproxy_str.len + CRLF_LEN, 0) == NULL) {
01593             LM_ERR("insert_new_lump_after failed\n");
01594             pkg_free(buf);
01595             return -1;
01596          }
01597       }
01598    }
01599 
01600    if (level & FIX_MEDIP) {
01601       /* Iterate all c= and replace ips in them. */
01602       if (replace_sdp_ip(msg, &body, "c=", str2?&ip:0)==-1)
01603          return -1;
01604    }
01605 
01606    if (level & FIX_ORGIP) {
01607       /* Iterate all o= and replace ips in them. */
01608       if (replace_sdp_ip(msg, &body, "o=", str2?&ip:0)==-1)
01609          return -1;
01610    }
01611 
01612    return 1;
01613 }
01614 
01615 static int
01616 extract_mediaip(str *body, str *mediaip, int *pf, char *line)
01617 {
01618    char *cp, *cp1;
01619    int len, nextisip;
01620 
01621    cp1 = NULL;
01622    for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
01623       cp1 = ser_memmem(cp, line, len, 2);
01624       if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
01625          break;
01626       cp = cp1 + 2;
01627    }
01628    if (cp1 == NULL)
01629       return -1;
01630 
01631    mediaip->s = cp1 + 2;
01632    mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
01633    trim_len(mediaip->len, mediaip->s, *mediaip);
01634 
01635    nextisip = 0;
01636    for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
01637       len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
01638       if (nextisip == 1) {
01639          mediaip->s = cp;
01640          mediaip->len = len;
01641          nextisip++;
01642          break;
01643       }
01644       if (len == 3 && memcmp(cp, "IP", 2) == 0) {
01645          switch (cp[2]) {
01646          case '4':
01647             nextisip = 1;
01648             *pf = AF_INET;
01649             break;
01650 
01651          case '6':
01652             nextisip = 1;
01653             *pf = AF_INET6;
01654             break;
01655 
01656          default:
01657             break;
01658          }
01659       }
01660       cp = eat_space_end(cp + len, mediaip->s + mediaip->len);
01661    }
01662    if (nextisip != 2 || mediaip->len == 0) {
01663       LM_ERR("no `IP[4|6]' in `%s' field\n",line);
01664       return -1;
01665    }
01666    return 1;
01667 }
01668 
01669 static int
01670 extract_mediainfo(str *body, str *mediaport, str *payload_types)
01671 {
01672    char *cp, *cp1;
01673    int len, i;
01674    str ptype;
01675 
01676    cp1 = NULL;
01677    for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
01678       cp1 = ser_memmem(cp, "m=", len, 2);
01679       if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
01680          break;
01681       cp = cp1 + 2;
01682    }
01683    if (cp1 == NULL) {
01684       LM_ERR("no `m=' in SDP\n");
01685       return -1;
01686    }
01687    mediaport->s = cp1 + 2; /* skip `m=' */
01688    mediaport->len = eat_line(mediaport->s, body->s + body->len -
01689      mediaport->s) - mediaport->s;
01690    trim_len(mediaport->len, mediaport->s, *mediaport);
01691 
01692    /* Skip media supertype and spaces after it */
01693    cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
01694    mediaport->len -= cp - mediaport->s;
01695    if (mediaport->len <= 0 || cp == mediaport->s) {
01696       LM_ERR("no port in `m='\n");
01697       return -1;
01698    }
01699    mediaport->s = cp;
01700    cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len);
01701    mediaport->len -= cp - mediaport->s;
01702    if (mediaport->len <= 0 || cp == mediaport->s) {
01703       LM_ERR("no port in `m='\n");
01704       return -1;
01705    }
01706    /* Extract port */
01707    mediaport->s = cp;
01708    cp = eat_token_end(mediaport->s, mediaport->s + mediaport->len);
01709    ptype.len = mediaport->len - (cp - mediaport->s);
01710    if (ptype.len <= 0 || cp == mediaport->s) {
01711       LM_ERR("no port in `m='\n");
01712       return -1;
01713    }
01714    ptype.s = cp;
01715    mediaport->len = cp - mediaport->s;
01716    /* Skip spaces after port */
01717    cp = eat_space_end(ptype.s, ptype.s + ptype.len);
01718    ptype.len -= cp - ptype.s;
01719    if (ptype.len <= 0 || cp == ptype.s) {
01720       LM_ERR("no protocol type in `m='\n");
01721       return -1;
01722    }
01723    /* Extract protocol type */
01724    ptype.s = cp;
01725    cp = eat_token_end(ptype.s, ptype.s + ptype.len);
01726    if (cp == ptype.s) {
01727       LM_ERR("no protocol type in `m='\n");
01728       return -1;
01729    }
01730    payload_types->len = ptype.len - (cp - ptype.s);
01731    ptype.len = cp - ptype.s;
01732    payload_types->s = cp;
01733 
01734    for (i = 0; sup_ptypes[i].s != NULL; i++) {
01735       if (ptype.len != sup_ptypes[i].len ||
01736           strncasecmp(ptype.s, sup_ptypes[i].s, ptype.len) != 0)
01737          continue;
01738       if (sup_ptypes[i].is_rtp == 0) {
01739          payload_types->len = 0;
01740          return 0;
01741       }
01742       cp = eat_space_end(payload_types->s, payload_types->s +
01743           payload_types->len);
01744       if (cp == payload_types->s) {
01745          LM_ERR("no payload types in `m='\n");
01746          return -1;
01747       }
01748       payload_types->len -= cp - payload_types->s;
01749       payload_types->s = cp;
01750       return 0;
01751    }
01752    /* Unproxyable protocol type. Generally it isn't error. */
01753    return -1;
01754 }
01755 
01756 /*
01757  * this function is ported from SER 
01758  */
01759 static int
01760 extract_rtcp(str *body, str *rtcpport)
01761 {
01762    char *cp, *cp1;
01763    int len;
01764 
01765    cp1 = NULL;
01766    for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
01767       cp1 = ser_memmem(cp, "a=rtcp:", len, 7);
01768       if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
01769          break;
01770       cp = cp1 + 7;
01771    }
01772 
01773    if (cp1 == NULL)
01774       return -1;
01775 
01776    rtcpport->s = cp1 + 7; /* skip `a=rtcp:' */
01777    rtcpport->len = eat_line(rtcpport->s, body->s + body->len -
01778              rtcpport->s) - rtcpport->s;
01779    trim_len(rtcpport->len, rtcpport->s, *rtcpport);
01780 
01781    return 0;
01782 }
01783 
01784 static int
01785 alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
01786   str *newip, int newpf, int preserve)
01787 {
01788    char *buf;
01789    int offset;
01790    struct lump* anchor;
01791    str omip, nip, oip;
01792 
01793    /* check that updating mediaip is really necessary */
01794    if (oldpf == newpf && isnulladdr(oldip, oldpf))
01795       return 0;
01796    if (newip->len == oldip->len &&
01797        memcmp(newip->s, oldip->s, newip->len) == 0)
01798       return 0;
01799 
01800    if (preserve != 0) {
01801       anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
01802       if (anchor == NULL) {
01803          LM_ERR("anchor_lump failed\n");
01804          return -1;
01805       }
01806       if (oldpf == AF_INET6) {
01807          omip.s = AOLDMEDIP6;
01808          omip.len = AOLDMEDIP6_LEN;
01809       } else {
01810          omip.s = AOLDMEDIP;
01811          omip.len = AOLDMEDIP_LEN;
01812       }
01813       buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
01814       if (buf == NULL) {
01815          LM_ERR("out of pkg memory\n");
01816          return -1;
01817       }
01818       memcpy(buf, CRLF, CRLF_LEN);
01819       memcpy(buf + CRLF_LEN, omip.s, omip.len);
01820       memcpy(buf + CRLF_LEN + omip.len, oldip->s, oldip->len);
01821       if (insert_new_lump_after(anchor, buf,
01822           omip.len + oldip->len + CRLF_LEN, 0) == NULL) {
01823          LM_ERR("insert_new_lump_after failed\n");
01824          pkg_free(buf);
01825          return -1;
01826       }
01827    }
01828 
01829    if (oldpf == newpf) {
01830       nip.len = newip->len;
01831       nip.s = pkg_malloc(nip.len);
01832       if (nip.s == NULL) {
01833          LM_ERR("out of pkg memory\n");
01834          return -1;
01835       }
01836       memcpy(nip.s, newip->s, newip->len);
01837    } else {
01838       nip.len = newip->len + 2;
01839       nip.s = pkg_malloc(nip.len);
01840       if (nip.s == NULL) {
01841          LM_ERR("out of pkg memory\n");
01842          return -1;
01843       }
01844       memcpy(nip.s + 2, newip->s, newip->len);
01845       nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
01846       nip.s[1] = ' ';
01847    }
01848 
01849    oip = *oldip;
01850    if (oldpf != newpf) {
01851       do {
01852          oip.s--;
01853          oip.len++;
01854       } while (*oip.s != '6' && *oip.s != '4');
01855    }
01856    offset = oip.s - msg->buf;
01857    anchor = del_lump(msg, offset, oip.len, 0);
01858    if (anchor == NULL) {
01859       LM_ERR("del_lump failed\n");
01860       pkg_free(nip.s);
01861       return -1;
01862    }
01863 
01864    if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
01865       LM_ERR("insert_new_lump_after failed\n");
01866       pkg_free(nip.s);
01867       return -1;
01868    }
01869    return 0;
01870 }
01871 
01872 static int
01873 alter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,
01874   int preserve)
01875 {
01876    char *buf;
01877    int offset;
01878    struct lump* anchor;
01879 
01880    /* check that updating mediaport is really necessary */
01881    if (newport->len == oldport->len &&
01882        memcmp(newport->s, oldport->s, newport->len) == 0)
01883       return 0;
01884 
01885    /*
01886     * Since rewriting the same info twice will mess SDP up,
01887     * apply simple anti foot shooting measure - put flag on
01888     * messages that have been altered and check it when
01889     * another request comes.
01890     */
01891 #if 0
01892    /* disabled: - it propagates to the reply and we don't want this
01893     *  -- andrei */
01894    if (msg->msg_flags & FL_SDP_PORT_AFS) {
01895       LM_ERR("you can't rewrite the same SDP twice, check your config!\n");
01896       return -1;
01897    }
01898 #endif
01899 
01900    if (preserve != 0) {
01901       anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
01902       if (anchor == NULL) {
01903          LM_ERR("anchor_lump failed\n");
01904          return -1;
01905       }
01906       buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN);
01907       if (buf == NULL) {
01908          LM_ERR("out of pkg memory\n");
01909          return -1;
01910       }
01911       memcpy(buf, CRLF, CRLF_LEN);
01912       memcpy(buf + CRLF_LEN, AOLDMEDPRT, AOLDMEDPRT_LEN);
01913       memcpy(buf + CRLF_LEN + AOLDMEDPRT_LEN, oldport->s, oldport->len);
01914       if (insert_new_lump_after(anchor, buf,
01915           AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) {
01916          LM_ERR("insert_new_lump_after failed\n");
01917          pkg_free(buf);
01918          return -1;
01919       }
01920    }
01921 
01922    buf = pkg_malloc(newport->len);
01923    if (buf == NULL) {
01924       LM_ERR("out of pkg memory\n");
01925       return -1;
01926    }
01927    offset = oldport->s - msg->buf;
01928    anchor = del_lump(msg, offset, oldport->len, 0);
01929    if (anchor == NULL) {
01930       LM_ERR("del_lump failed\n");
01931       pkg_free(buf);
01932       return -1;
01933    }
01934    memcpy(buf, newport->s, newport->len);
01935    if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
01936       LM_ERR("insert_new_lump_after failed\n");
01937       pkg_free(buf);
01938       return -1;
01939    }
01940 
01941 #if 0
01942    msg->msg_flags |= FL_SDP_PORT_AFS;
01943 #endif
01944    return 0;
01945 }
01946 
01947 /*
01948  * this function is ported from SER 
01949  */
01950 static int
01951 alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport)
01952 {
01953    char *buf;
01954    int offset;
01955    struct lump* anchor;
01956 
01957    /* check that updating rtcpport is really necessary */
01958    if (newport->len == oldport->len &&
01959        memcmp(newport->s, oldport->s, newport->len) == 0)
01960       return 0;
01961 
01962    buf = pkg_malloc(newport->len);
01963    if (buf == NULL) {
01964       LM_ERR("alter_rtcp: out of memory\n");
01965       return -1;
01966    }
01967    offset = oldport->s - msg->buf;
01968    anchor = del_lump(msg, offset, oldport->len, 0);
01969    if (anchor == NULL) {
01970       LM_ERR("alter_rtcp: del_lump failed\n");
01971       pkg_free(buf);
01972       return -1;
01973    }
01974    memcpy(buf, newport->s, newport->len);
01975    if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
01976       LM_ERR("alter_rtcp: insert_new_lump_after failed\n");
01977       pkg_free(buf);
01978       return -1;
01979    }
01980 
01981    return 0;
01982 }
01983 
01984 static char * gencookie(void)
01985 {
01986    static char cook[34];
01987 
01988    sprintf(cook, "%d_%u ", (int)mypid, myseqn);
01989    myseqn++;
01990    return cook;
01991 }
01992 
01993 static int
01994 rtpp_checkcap(struct rtpp_node *node, char *cap, int caplen)
01995 {
01996    char *cp;
01997    struct iovec vf[4] = {{NULL, 0}, {"VF", 2}, {" ", 1}, {NULL, 0}};
01998 
01999    vf[3].iov_base = cap;
02000    vf[3].iov_len = caplen;
02001 
02002    cp = send_rtpp_command(node, vf, 4);
02003    if (cp == NULL)
02004       return -1;
02005    if (cp[0] == 'E' || atoi(cp) != 1)
02006       return 0;
02007    return 1;
02008 }
02009 
02010 static int
02011 rtpp_test(struct rtpp_node *node, int isdisabled, int force)
02012 {
02013    int rtpp_ver, rval;
02014    char *cp;
02015    struct iovec v[2] = {{NULL, 0}, {"V", 1}};
02016 
02017    if(node->rn_recheck_ticks == MI_MAX_RECHECK_TICKS){
02018        LM_DBG("rtpp %s disabled for ever\n", node->rn_url.s);
02019       return 1;
02020    }
02021 
02022    if (force == 0) {
02023       if (isdisabled == 0)
02024          return 0;
02025       if (node->rn_recheck_ticks > get_ticks())
02026          return 1;
02027    }
02028    cp = send_rtpp_command(node, v, 2);
02029    if (cp == NULL) {
02030       LM_WARN("can't get version of the RTP proxy\n");
02031       goto error;
02032    }
02033    rtpp_ver = atoi(cp);
02034    if (rtpp_ver != SUP_CPROTOVER) {
02035       LM_WARN("unsupported version of RTP proxy <%s> found: %d supported,"
02036             "%d present\n", node->rn_url.s, SUP_CPROTOVER, rtpp_ver);
02037       goto error;
02038    }
02039    rval = rtpp_checkcap(node, REQ_CPROTOVER, sizeof(REQ_CPROTOVER) - 1);
02040    if (rval == -1) {
02041       LM_WARN("RTP proxy went down during version query\n");
02042       goto error;
02043    }
02044    if (rval == 0) {
02045       LM_WARN("of RTP proxy <%s> doesn't support required protocol version"
02046             "%s\n", node->rn_url.s, REQ_CPROTOVER);
02047       goto error;
02048    }
02049    LM_INFO("rtp proxy <%s> found, support for it %senabled\n",
02050        node->rn_url.s, force == 0 ? "re-" : "");
02051    /* Check for optional capabilities */
02052    rval = rtpp_checkcap(node, REP_CPROTOVER, sizeof(REP_CPROTOVER) - 1);
02053    if (rval != -1) {
02054       node->rn_rep_supported = rval;
02055    } else {
02056       node->rn_rep_supported = 0;
02057    }
02058    rval = rtpp_checkcap(node, PTL_CPROTOVER, sizeof(PTL_CPROTOVER) - 1);
02059    if (rval != -1) {
02060       node->rn_ptl_supported = rval;
02061    } else {
02062       node->rn_ptl_supported = 0;
02063    }
02064    return 0;
02065 error:
02066    LM_WARN("support for RTP proxy <%s> has been disabled%s\n", node->rn_url.s,
02067        rtpproxy_disable_tout < 0 ? "" : " temporarily");
02068    if (rtpproxy_disable_tout >= 0)
02069       node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
02070 
02071    return 1;
02072 }
02073 
02074 char *
02075 send_rtpp_command(struct rtpp_node *node, struct iovec *v, int vcnt)
02076 {
02077    struct sockaddr_un addr;
02078    int fd, len, i;
02079    char *cp;
02080    static char buf[256];
02081    struct pollfd fds[1];
02082 
02083    len = 0;
02084    cp = buf;
02085    if (node->rn_umode == 0) {
02086       memset(&addr, 0, sizeof(addr));
02087       addr.sun_family = AF_LOCAL;
02088       strncpy(addr.sun_path, node->rn_address,
02089           sizeof(addr.sun_path) - 1);
02090 #ifdef HAVE_SOCKADDR_SA_LEN
02091       addr.sun_len = strlen(addr.sun_path);
02092 #endif
02093 
02094       fd = socket(AF_LOCAL, SOCK_STREAM, 0);
02095       if (fd < 0) {
02096          LM_ERR("can't create socket\n");
02097          goto badproxy;
02098       }
02099       if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
02100          close(fd);
02101          LM_ERR("can't connect to RTP proxy\n");
02102          goto badproxy;
02103       }
02104 
02105       do {
02106          len = writev(fd, v + 1, vcnt - 1);
02107       } while (len == -1 && errno == EINTR);
02108       if (len <= 0) {
02109          close(fd);
02110          LM_ERR("can't send command to a RTP proxy\n");
02111          goto badproxy;
02112       }
02113       do {
02114          len = read(fd, buf, sizeof(buf) - 1);
02115       } while (len == -1 && errno == EINTR);
02116       close(fd);
02117       if (len <= 0) {
02118          LM_ERR("can't read reply from a RTP proxy\n");
02119          goto badproxy;
02120       }
02121    } else {
02122       fds[0].fd = rtpp_socks[node->idx];
02123       fds[0].events = POLLIN;
02124       fds[0].revents = 0;
02125       /* Drain input buffer */
02126       while ((poll(fds, 1, 0) == 1) &&
02127           ((fds[0].revents & POLLIN) != 0)) {
02128          recv(rtpp_socks[node->idx], buf, sizeof(buf) - 1, 0);
02129          fds[0].revents = 0;
02130       }
02131       v[0].iov_base = gencookie();
02132       v[0].iov_len = strlen(v[0].iov_base);
02133       for (i = 0; i < rtpproxy_retr; i++) {
02134          do {
02135             len = writev(rtpp_socks[node->idx], v, vcnt);
02136          } while (len == -1 && (errno == EINTR || errno == ENOBUFS));
02137          if (len <= 0) {
02138             LM_ERR("can't send command to a RTP proxy\n");
02139             goto badproxy;
02140          }
02141          while ((poll(fds, 1, rtpproxy_tout * 1000) == 1) &&
02142              (fds[0].revents & POLLIN) != 0) {
02143             do {
02144                len = recv(rtpp_socks[node->idx], buf, sizeof(buf)-1, 0);
02145             } while (len == -1 && errno == EINTR);
02146             if (len <= 0) {
02147                LM_ERR("can't read reply from a RTP proxy\n");
02148                goto badproxy;
02149             }
02150             if (len >= (v[0].iov_len - 1) &&
02151                 memcmp(buf, v[0].iov_base, (v[0].iov_len - 1)) == 0) {
02152                len -= (v[0].iov_len - 1);
02153                cp += (v[0].iov_len - 1);
02154                if (len != 0) {
02155                   len--;
02156                   cp++;
02157                }
02158                goto out;
02159             }
02160             fds[0].revents = 0;
02161          }
02162       }
02163       if (i == rtpproxy_retr) {
02164          LM_ERR("timeout waiting reply from a RTP proxy\n");
02165          goto badproxy;
02166       }
02167    }
02168 
02169 out:
02170    cp[len] = '\0';
02171    return cp;
02172 badproxy:
02173    LM_ERR("proxy <%s> does not respond, disable it\n", node->rn_url.s);
02174    node->rn_disabled = 1;
02175    node->rn_recheck_ticks = get_ticks() + rtpproxy_disable_tout;
02176    
02177    return NULL;
02178 }
02179 
02180 /*
02181  * select the set with the id_set id
02182  */
02183 
02184 static struct rtpp_set * select_rtpp_set(int id_set ){
02185 
02186    struct rtpp_set * rtpp_list;
02187    /*is it a valid set_id?*/
02188    
02189    if(!rtpp_set_list || !rtpp_set_list->rset_first){
02190       LM_ERR("no rtp_proxy configured\n");
02191       return 0;
02192    }
02193 
02194    for(rtpp_list=rtpp_set_list->rset_first; rtpp_list!=0 && 
02195       rtpp_list->id_set!=id_set; rtpp_list=rtpp_list->rset_next);
02196    if(!rtpp_list){
02197       LM_ERR(" script error-invalid id_set to be selected\n");
02198    }
02199 
02200    return rtpp_list;
02201 }
02202 /*
02203  * Main balancing routine. This does not try to keep the same proxy for
02204  * the call if some proxies were disabled or enabled; proxy death considered
02205  * too rare. Otherwise we should implement "mature" HA clustering, which is
02206  * too expensive here.
02207  */
02208 struct rtpp_node *
02209 select_rtpp_node(str callid, int do_test)
02210 {
02211    unsigned sum, sumcut, weight_sum;
02212    struct rtpp_node* node;
02213    int was_forced;
02214 
02215    if(!selected_rtpp_set){
02216       LM_ERR("script error -no valid set selected\n");
02217       return NULL;
02218    }
02219    /* Most popular case: 1 proxy, nothing to calculate */
02220    if (selected_rtpp_set->rtpp_node_count == 1) {
02221       node = selected_rtpp_set->rn_first;
02222       if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks())
02223          node->rn_disabled = rtpp_test(node, 1, 0);
02224       return node->rn_disabled ? NULL : node;
02225    }
02226 
02227    /* XXX Use quick-and-dirty hashing algo */
02228    for(sum = 0; callid.len > 0; callid.len--)
02229       sum += callid.s[callid.len - 1];
02230    sum &= 0xff;
02231 
02232    was_forced = 0;
02233 retry:
02234    weight_sum = 0;
02235    for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
02236 
02237       if (node->rn_disabled && node->rn_recheck_ticks <= get_ticks()){
02238          /* Try to enable if it's time to try. */
02239          node->rn_disabled = rtpp_test(node, 1, 0);
02240       }
02241       if (!node->rn_disabled)
02242          weight_sum += node->rn_weight;
02243    }
02244    if (weight_sum == 0) {
02245       /* No proxies? Force all to be redetected, if not yet */
02246       if (was_forced)
02247          return NULL;
02248       was_forced = 1;
02249       for(node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
02250          node->rn_disabled = rtpp_test(node, 1, 1);
02251       }
02252       goto retry;
02253    }
02254    sumcut = sum % weight_sum;
02255    /*
02256     * sumcut here lays from 0 to weight_sum-1.
02257     * Scan proxy list and decrease until appropriate proxy is found.
02258     */
02259    for (node=selected_rtpp_set->rn_first; node!=NULL; node=node->rn_next) {
02260       if (node->rn_disabled)
02261          continue;
02262       if (sumcut < node->rn_weight)
02263          goto found;
02264       sumcut -= node->rn_weight;
02265    }
02266    /* No node list */
02267    return NULL;
02268 found:
02269    if (do_test) {
02270       node->rn_disabled = rtpp_test(node, node->rn_disabled, 0);
02271       if (node->rn_disabled)
02272          goto retry;
02273    }
02274    return node;
02275 }
02276 
02277 static int
02278 unforce_rtp_proxy_f(struct sip_msg* msg, char* str1, char* str2)
02279 {
02280    str callid, from_tag, to_tag;
02281    struct rtpp_node *node;
02282    struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"D", 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
02283                   /* 1 */   /* 2 */   /* 3 */    /* 4 */   /* 5 */    /* 6 */   /* 1 */
02284 
02285    if (get_callid(msg, &callid) == -1 || callid.len == 0) {
02286       LM_ERR("can't get Call-Id field\n");
02287       return -1;
02288    }
02289    to_tag.s = 0;
02290    if (get_to_tag(msg, &to_tag) == -1) {
02291       LM_ERR("can't get To tag\n");
02292       return -1;
02293    }
02294    if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
02295       LM_ERR("can't get From tag\n");
02296       return -1;
02297    }
02298    STR2IOVEC(callid, v[3]);
02299    STR2IOVEC(from_tag, v[5]);
02300    STR2IOVEC(to_tag, v[7]);
02301    
02302    if(msg->id != current_msg_id){
02303       selected_rtpp_set = default_rtpp_set;
02304    }
02305    
02306    node = select_rtpp_node(callid, 1);
02307    if (!node) {
02308       LM_ERR("no available proxies\n");
02309       return -1;
02310    }
02311    send_rtpp_command(node, v, (to_tag.len > 0) ? 8 : 6);
02312 
02313    return 1;
02314 }
02315 
02316 /*
02317  * Auxiliary for some functions.
02318  * Returns pointer to first character of found line, or NULL if no such line.
02319  */
02320 
02321 static char *
02322 find_sdp_line(char* p, char* plimit, char linechar)
02323 {
02324    static char linehead[3] = "x=";
02325    char *cp, *cp1;
02326    linehead[0] = linechar;
02327    /* Iterate thru body */
02328    cp = p;
02329    for (;;) {
02330       if (cp >= plimit)
02331          return NULL;
02332       cp1 = ser_memmem(cp, linehead, plimit-cp, 2);
02333       if (cp1 == NULL)
02334          return NULL;
02335       /*
02336        * As it is body, we assume it has previous line and we can
02337        * lookup previous character.
02338        */
02339       if (cp1[-1] == '\n' || cp1[-1] == '\r')
02340          return cp1;
02341       /*
02342        * Having such data, but not at line beginning.
02343        * Skip them and reiterate. ser_memmem() will find next
02344        * occurence.
02345        */
02346       if (plimit - cp1 < 2)
02347          return NULL;
02348       cp = cp1 + 2;
02349    }
02350 }
02351 
02352 /* This function assumes p points to a line of requested type. */
02353 
02354 static char *
02355 find_next_sdp_line(char* p, char* plimit, char linechar, char* defptr)
02356 {
02357    char *t;
02358    if (p >= plimit || plimit - p < 3)
02359       return defptr;
02360    t = find_sdp_line(p + 2, plimit, linechar);
02361    return t ? t : defptr;
02362 }
02363 
02364 static int
02365 set_rtp_proxy_set_f(struct sip_msg * msg, char * str1, char * str2)
02366 {
02367    current_msg_id = msg->id;
02368    selected_rtpp_set = (struct rtpp_set *)str1;
02369    return 1;
02370 }
02371 
02372 static int
02373 rtpproxy_offer1_f(struct sip_msg *msg, char *str1, char *str2)
02374 {
02375         char *cp;
02376         char newip[IP_ADDR_MAX_STR_SIZE];
02377 
02378         cp = ip_addr2a(&msg->rcv.dst_ip);
02379         strcpy(newip, cp);
02380    return rtpproxy_offer2_f(msg, str1, newip);
02381 }
02382 
02383 static int
02384 rtpproxy_offer2_f(struct sip_msg *msg, char *param1, char *param2)
02385 {
02386 
02387    if (msg->first_line.type == SIP_REQUEST)
02388       if (msg->first_line.u.request.method_value != METHOD_INVITE)
02389          return -1;
02390 
02391    return force_rtp_proxy(msg, param1, param2, 1);
02392 }
02393 
02394 static int
02395 rtpproxy_answer1_f(struct sip_msg *msg, char *str1, char *str2)
02396 {
02397         char *cp;
02398         char newip[IP_ADDR_MAX_STR_SIZE];
02399 
02400         cp = ip_addr2a(&msg->rcv.dst_ip);
02401         strcpy(newip, cp);
02402         return rtpproxy_answer2_f(msg, str1, newip);
02403 }
02404 
02405 static int
02406 rtpproxy_answer2_f(struct sip_msg *msg, char *param1, char *param2)
02407 {
02408 
02409    if (msg->first_line.type == SIP_REQUEST)
02410       if (msg->first_line.u.request.method_value != METHOD_ACK)
02411          return -1;
02412 
02413    return force_rtp_proxy(msg, param1, param2, 0);
02414 }
02415 
02416 static int
02417 force_rtp_proxy2_f(struct sip_msg *msg, char *param1, char *param2)
02418 {
02419    int offer;
02420 
02421    if (msg->first_line.type == SIP_REQUEST &&
02422        msg->first_line.u.request.method_value == METHOD_INVITE) {
02423       offer = 1;
02424    } else if (msg->first_line.type == SIP_REPLY) {
02425       offer = 0;
02426    } else {
02427       return -1;
02428    }
02429 
02430    return force_rtp_proxy(msg, param1, param2, offer);
02431 }
02432 
02433 static int
02434 force_rtp_proxy(struct sip_msg* msg, char* str1, char* str2, int offer)
02435 {
02436    str body, body1, oldport, oldip, newport, newip;
02437    str callid, from_tag, to_tag, tmp, payload_types;
02438    str oldrtcp, newrtcp;
02439    int create, port, len, asymmetric, flookup, argc, proxied, real;
02440    int orgip, commip;
02441    int oidx, pf, pf1, force, swap, rep_oidx;
02442    char opts[32];
02443    char rep_opts[16];
02444    char *cp, *cp1;
02445    char  *cpend, *next;
02446    char **ap, *argv[10];
02447    struct lump* anchor;
02448    struct rtpp_node *node;
02449    struct iovec v[16] = {
02450       {NULL, 0},  /* command */
02451       {NULL, 0},  /* options */
02452       {" ", 1},   /* separator */
02453       {NULL, 0},  /* callid */
02454       {" ", 1},   /* separator */
02455       {NULL, 7},  /* newip */
02456       {" ", 1},   /* separator */
02457       {NULL, 1},  /* oldport */
02458       {" ", 1},   /* separator */
02459       {NULL, 0},  /* from_tag */
02460       {";", 1},   /* separator */
02461       {NULL, 0},  /* medianum */
02462       {" ", 1},   /* separator */
02463       {NULL, 0},  /* to_tag */
02464       {";", 1},   /* separator */
02465       {NULL, 0}   /* medianum */
02466    };
02467    char *v1p, *v2p, *c1p, *c2p, *m1p, *m2p, *bodylimit, *o1p;
02468    char medianum_buf[20];
02469    int medianum, media_multi;
02470    str medianum_str, tmpstr1;
02471    int c1p_altered;
02472    static int swap_warned = 0;
02473 
02474    v[1].iov_base=opts;
02475    asymmetric = flookup = force = real = orgip = commip = swap = 0;
02476    oidx = 1;
02477    rep_oidx = 0;
02478    for (cp = str1; cp != NULL && *cp != '\0'; cp++) {
02479       switch (*cp) {
02480       case 'a':
02481       case 'A':
02482          opts[oidx++] = 'A';
02483          asymmetric = 1;
02484          real = 1;
02485          break;
02486 
02487       case 'i':
02488       case 'I':
02489          opts[oidx++] = 'I';
02490          break;
02491 
02492       case 'e':
02493       case 'E':
02494          opts[oidx++] = 'E';
02495          break;
02496 
02497       case 'l':
02498       case 'L':
02499          if (offer == 0)
02500             return -1;
02501          flookup = 1;
02502          break;
02503 
02504       case 'f':
02505       case 'F':
02506          force = 1;
02507          break;
02508 
02509       case 'r':
02510       case 'R':
02511          real = 1;
02512          break;
02513 
02514       case 'c':
02515       case 'C':
02516          commip = 1;
02517          break;
02518 
02519       case 'o':
02520       case 'O':
02521          orgip = 1;
02522          break;
02523 
02524       case 's':
02525       case 'S':
02526          swap = 1;
02527          if (swap_warned != 0)
02528             break;
02529          LM_WARN("swap flag (`%c') is depreciated, use "
02530              "rtpproxy_offer() and rtpproxy_answer() "
02531              "instead\n", *cp);
02532          swap_warned = 1;
02533          break;
02534 
02535       case 'w':
02536       case 'W':
02537          opts[oidx++] = 'S';
02538          break;
02539 
02540       case 'z':
02541       case 'Z':
02542          rep_opts[rep_oidx++] = 'Z';
02543          /* If there are any digits following Z copy them into the command */
02544          for (; cp[1] != '\0' && isdigit(cp[1]); cp++)
02545             rep_opts[rep_oidx++] = cp[1];
02546          break;
02547 
02548       default:
02549          LM_ERR("unknown option `%c'\n", *cp);
02550          return -1;
02551       }
02552    }
02553 
02554    if (offer != 0) {
02555       create = swap?0:1;
02556    } else {
02557       create = swap?1:0;
02558    }
02559    /* extract_body will also parse all the headers in the message as
02560     * a side effect => don't move get_callid/get_to_tag in front of it
02561     * -- andrei */
02562    if (extract_body(msg, &body) == -1) {
02563       LM_ERR("can't extract body from the message\n");
02564       return -1;
02565    }
02566    if (get_callid(msg, &callid) == -1 || callid.len == 0) {
02567       LM_ERR("can't get Call-Id field\n");
02568       return -1;
02569    }
02570    to_tag.s = 0;
02571    if (get_to_tag(msg, &to_tag) == -1) {
02572       LM_ERR("can't get To tag\n");
02573       return -1;
02574    }
02575    if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
02576       LM_ERR("can't get From tag\n");
02577       return -1;
02578    }
02579    /*  LOGIC
02580     *  ------
02581     *  1) NO SWAP (create on request, lookup on reply):
02582     *       req -> create = 1
02583     *       rpl -> create = 0
02584     *       if (forced_lookup) -> create = 0;
02585     *
02586     *  2) SWAP (create on reply, lookup on request):
02587     *       req -> create = 0
02588     *       rpl -> create = 1
02589     *       swap_tags
02590     *       if (forced_lookup) -> create = 0;
02591     */
02592    if (flookup != 0) {
02593       if (to_tag.len == 0)
02594          return -1;
02595       create = 0;
02596       if (swap != 0) {
02597          tmp = from_tag;
02598          from_tag = to_tag;
02599          to_tag = tmp;
02600       }
02601    } else if (swap != 0 || (msg->first_line.type == SIP_REPLY && offer != 0)) {
02602       if (to_tag.len == 0)
02603          return -1;
02604       tmp = from_tag;
02605       from_tag = to_tag;
02606       to_tag = tmp;
02607    }
02608    proxied = 0;
02609    if (nortpproxy_str.len) {
02610       for ( cp=body.s ; (len=body.s+body.len-cp) >= nortpproxy_str.len ; ) {
02611          cp1 = ser_memmem(cp, nortpproxy_str.s, len, nortpproxy_str.len);
02612          if (cp1 == NULL)
02613             break;
02614          if (cp1[-1] == '\n' || cp1[-1] == '\r') {
02615             proxied = 1;
02616             break;
02617          }
02618          cp = cp1 + nortpproxy_str.len;
02619       }
02620    }
02621    if (proxied != 0 && force == 0)
02622       return -1;
02623    /*
02624     * Parsing of SDP body.
02625     * It can contain a few session descriptions (each starts with
02626     * v-line), and each session may contain a few media descriptions
02627     * (each starts with m-line).
02628     * We have to change ports in m-lines, and also change IP addresses in
02629     * c-lines which can be placed either in session header (fallback for
02630     * all medias) or media description.
02631     * Ports should be allocated for any media. IPs all should be changed
02632     * to the same value (RTP proxy IP), so we can change all c-lines
02633     * unconditionally.
02634     */
02635    bodylimit = body.s + body.len;
02636    v1p = find_sdp_line(body.s, bodylimit, 'v');
02637    if (v1p == NULL) {
02638       LM_ERR("no sessions in SDP\n");
02639       return -1;
02640    }
02641    v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
02642    media_multi = (v2p != bodylimit);
02643    v2p = v1p;
02644    medianum = 0;
02645 
02646    if(msg->id != current_msg_id){
02647       selected_rtpp_set = default_rtpp_set;
02648    }
02649 
02650    for(;;) {
02651       /* Per-session iteration. */
02652       v1p = v2p;
02653       if (v1p == NULL || v1p >= bodylimit)
02654          break; /* No sessions left */
02655       v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
02656       /* v2p is text limit for session parsing. */
02657       /* get session origin */
02658       o1p = find_sdp_line(v1p, v2p, 'o');
02659       if (o1p==0) {
02660          LM_ERR("no o= in session\n");
02661          return -1;
02662       }
02663       /* Have this session media description? */
02664       m1p = find_sdp_line(o1p, v2p, 'm');
02665       if (m1p == NULL) {
02666          LM_ERR("no m= in session\n");
02667          return -1;
02668       }
02669       /*
02670        * Find c1p only between session begin and first media.
02671        * c1p will give common c= for all medias.
02672        */
02673       c1p = find_sdp_line(o1p, m1p, 'c');
02674       c1p_altered = 0;
02675       if (orgip==0)
02676          o1p = 0;
02677       /* Have session. Iterate media descriptions in session */
02678       m2p = m1p;
02679       for (;;) {
02680          m1p = m2p;
02681          if (m1p == NULL || m1p >= v2p)
02682             break;
02683          m2p = find_next_sdp_line(m1p, v2p, 'm', v2p);
02684          /* c2p will point to per-media "c=" */
02685          c2p = find_sdp_line(m1p, m2p, 'c');
02686          /* Extract address and port */
02687          tmpstr1.s = c2p ? c2p : c1p;
02688          if (tmpstr1.s == NULL) {
02689             /* No "c=" */
02690             LM_ERR("can't find media IP in the message\n");
02691             return -1;
02692          }
02693          tmpstr1.len = v2p - tmpstr1.s; /* limit is session limit text */
02694          if (extract_mediaip(&tmpstr1, &oldip, &pf,"c=") == -1) {
02695             LM_ERR("can't extract media IP from the message\n");
02696             return -1;
02697          }
02698          tmpstr1.s = m1p;
02699          tmpstr1.len = m2p - m1p;
02700          if (extract_mediainfo(&tmpstr1, &oldport, &payload_types) == -1) {
02701             LM_ERR("can't extract media port from the message\n");
02702             return -1;
02703          }
02704          /* Extract rtcp attribute,ported from SER */
02705          tmpstr1.s = m1p;
02706          tmpstr1.len = m2p - m1p;
02707          oldrtcp.s = NULL;
02708          oldrtcp.len = 0;
02709          extract_rtcp(&tmpstr1, &oldrtcp);
02710          
02711          ++medianum;
02712          if (asymmetric != 0 || real != 0) {
02713             newip = oldip;
02714          } else {
02715             newip.s = ip_addr2a(&msg->rcv.src_ip);
02716             newip.len = strlen(newip.s);
02717          }
02718          /* XXX must compare address families in all addresses */
02719          if (pf == AF_INET6) {
02720             opts[oidx] = '6';
02721             oidx++;
02722          }
02723          opts[0] = (create == 0) ? 'L' : 'U';
02724          v[1].iov_len = oidx;
02725          STR2IOVEC(callid, v[3]);
02726          STR2IOVEC(newip, v[5]);
02727          STR2IOVEC(oldport, v[7]);
02728          STR2IOVEC(from_tag, v[9]);
02729          if (1 || media_multi) /* XXX netch: can't choose now*/
02730          {
02731             snprintf(medianum_buf, sizeof medianum_buf, "%d", medianum);
02732             medianum_str.s = medianum_buf;
02733             medianum_str.len = strlen(medianum_buf);
02734             STR2IOVEC(medianum_str, v[11]);
02735             STR2IOVEC(medianum_str, v[15]);
02736          } else {
02737             v[10].iov_len = v[11].iov_len = 0;
02738             v[14].iov_len = v[15].iov_len = 0;
02739          }
02740          STR2IOVEC(to_tag, v[13]);
02741          do {
02742             node = select_rtpp_node(callid, 1);
02743             if (!node) {
02744                LM_ERR("no available proxies\n");
02745                return -1;
02746             }
02747             len = v[1].iov_len;
02748             if (rep_oidx > 0) {
02749                if (node->rn_rep_supported == 0) {
02750                   LM_WARN("re-packetization is requested but is not "
02751                       "supported by the selected RTP proxy node\n");
02752                } else {
02753                   memcpy((char *)v[1].iov_base + v[1].iov_len,
02754                       rep_opts, rep_oidx);
02755                   v[1].iov_len += rep_oidx;
02756                }
02757             }
02758             if (payload_types.len > 0 && node->rn_ptl_supported != 0) {
02759                cp1 = (char *)v[1].iov_base + v[1].iov_len;
02760                *cp1 = 'c';
02761                cp1++;
02762                /*
02763                 * Convert space-separated payload types list into
02764                 * a comma-separated list.
02765                 */
02766                for (cp = payload_types.s;
02767                    cp < payload_types.s + payload_types.len; cp++) {
02768                   if (isdigit(*cp)) {
02769                      *cp1 = *cp;
02770                      cp1++;
02771                      continue;
02772                   }
02773                   *cp1 = ',';
02774                   cp1++;
02775                   do {
02776                      cp++;
02777                   } while (!isdigit(*cp) &&
02778                       cp < payload_types.s + payload_types.len);
02779                   cp--;
02780                }
02781                v[1].iov_len = cp1 - (char *)v[1].iov_base;
02782             }
02783             cp = send_rtpp_command(node, v, (to_tag.len > 0) ? 16 : 12);
02784             v[1].iov_len = len;
02785          } while (cp == NULL);
02786          LM_DBG("proxy reply: %s\n", cp);
02787          /* Parse proxy reply to <argc,argv> */
02788          argc = 0;
02789          memset(argv, 0, sizeof(argv));
02790          cpend=cp+strlen(cp);
02791          next=eat_token_end(cp, cpend);
02792          for (ap=argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){
02793             *next=0;
02794             if (*cp != '\0') {
02795                *ap=cp;
02796                argc++;
02797                if ((char*)++ap >= ((char*)argv+sizeof(argv)))
02798                   break;
02799             }
02800          }
02801          if (argc < 1) {
02802             LM_ERR("no reply from rtp proxy\n");
02803             return -1;
02804          }
02805          port = atoi(argv[0]);
02806          if (port <= 0 || port > 65535) {
02807             if (port != 0 || flookup == 0)
02808                LM_ERR("incorrect port %i in reply "
02809                   "from rtp proxy\n",port);
02810             return -1;
02811          }
02812 
02813          pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET;
02814 
02815          if (isnulladdr(&oldip, pf)) {
02816             if (pf1 == AF_INET6) {
02817                newip.s = "::";
02818                newip.len = 2;
02819             } else {
02820                newip.s = "0.0.0.0";
02821                newip.len = 7;
02822             }
02823          } else {
02824             newip.s = (argc < 2) ? str2 : argv[1];
02825             newip.len = strlen(newip.s);
02826          }
02827          /* marker to double check : newport goes: str -> int -> str ?!?! */
02828          newport.s = int2str(port, &newport.len); /* beware static buffer */
02829          /* Alter port. */
02830          body1.s = m1p;
02831          body1.len = bodylimit - body1.s;
02832          /* do not do it if old port was 0 (means media disable)
02833           * - check if actually should be better done in rtpptoxy,
02834           *   by returning also 0
02835           * - or by not sending to rtpproxy the old port if 0
02836           */
02837          if(oldport.len!=1 || oldport.s[0]!='0')
02838          {
02839             if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1)
02840                return -1;
02841          }
02842          
02843          /*
02844           * Alter RTCP attribute if present. Inserting RTP port + 1 (as allocated
02845           * by RTP proxy). No IP-address is needed in the new RTCP attribute as the
02846           * 'c' attribute (altered below) will contain the RTP proxy IP address.
02847           * See RFC 3605 for definition of RTCP attribute.
02848              * ported from ser
02849           */
02850          if (oldrtcp.s && oldrtcp.len) {
02851             newrtcp.s = int2str(port+1, &newrtcp.len); /* beware static buffer */
02852             /* Alter port. */
02853             body1.s = m1p;
02854             body1.len = bodylimit - body1.s;
02855             if (alter_rtcp(msg, &body1, &oldrtcp, &newrtcp) == -1)
02856                return -1;
02857          }        
02858          
02859          
02860          /*
02861           * Alter IP. Don't alter IP common for the session
02862           * more than once.
02863           */
02864          if (c2p != NULL || !c1p_altered) {
02865             body1.s = c2p ? c2p : c1p;
02866             body1.len = bodylimit - body1.s;
02867             if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0)==-1)
02868                return -1;
02869             if (!c2p)
02870                c1p_altered = 1;
02871          }
02872          /*
02873           * Alter common IP if required, but don't do it more than once.
02874           */
02875          if (commip && c1p && !c1p_altered) {
02876             tmpstr1.s = c1p;
02877             tmpstr1.len = v2p - tmpstr1.s;
02878             if (extract_mediaip(&tmpstr1, &oldip, &pf,"c=") == -1) {
02879                LM_ERR("can't extract media IP from the message\n");
02880                return -1;
02881             }
02882             body1.s = c1p;
02883             body1.len = bodylimit - body1.s;
02884             if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0)==-1)
02885                return -1;
02886             c1p_altered = 1;
02887          }
02888          /*
02889           * Alter the IP in "o=", but only once per session
02890           */
02891          if (o1p) {
02892             tmpstr1.s = o1p;
02893             tmpstr1.len = v2p - tmpstr1.s;
02894             if (extract_mediaip(&tmpstr1, &oldip, &pf,"o=") == -1) {
02895                LM_ERR("can't extract media IP from the message\n");
02896                return -1;
02897             }
02898             body1.s = o1p;
02899             body1.len = bodylimit - body1.s;
02900             if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0)==-1)
02901                return -1;
02902             o1p = 0;
02903          }
02904       } /* Iterate medias in session */
02905    } /* Iterate sessions */
02906 
02907    if (proxied == 0 && nortpproxy_str.len) {
02908       cp = pkg_malloc((nortpproxy_str.len + CRLF_LEN) * sizeof(char));
02909       if (cp == NULL) {
02910          LM_ERR("out of pkg memory\n");
02911          return -1;
02912       }
02913       anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
02914       if (anchor == NULL) {
02915          LM_ERR("anchor_lump failed\n");
02916          pkg_free(cp);
02917          return -1;
02918       }
02919       memcpy(cp, CRLF, CRLF_LEN);
02920       memcpy(cp + CRLF_LEN, nortpproxy_str.s, nortpproxy_str.len);
02921       if (insert_new_lump_after(anchor, cp, nortpproxy_str.len + CRLF_LEN, 0) == NULL) {
02922          LM_ERR("insert_new_lump_after failed\n");
02923          pkg_free(cp);
02924          return -1;
02925       }
02926    }
02927 
02928    return 1;
02929 }
02930 
02931 static int
02932 force_rtp_proxy1_f(struct sip_msg* msg, char* str1, char* str2)
02933 {
02934    char *cp;
02935    char newip[IP_ADDR_MAX_STR_SIZE];
02936 
02937    cp = ip_addr2a(&msg->rcv.dst_ip);
02938    strcpy(newip, cp);
02939 
02940    return force_rtp_proxy2_f(msg, str1, newip);
02941 }
02942 
02943 static int
02944 force_rtp_proxy0_f(struct sip_msg* msg, char* str1, char* str2)
02945 {
02946    char arg[1] = {'\0'};
02947 
02948    return force_rtp_proxy1_f(msg, arg, NULL);
02949 }
02950 
02951 
02952 static u_short raw_checksum(unsigned char *buffer, int len)
02953 {
02954    u_long sum = 0;
02955 
02956    while (len > 1) {
02957       sum += *buffer << 8;
02958       buffer++;
02959       sum += *buffer;
02960       buffer++;
02961       len -= 2;
02962    }
02963    if (len) {
02964       sum += *buffer << 8;
02965    }
02966    sum = (sum >> 16) + (sum & 0xffff);
02967    sum = (sum >> 16) + (sum);
02968 
02969    return (u_short) ~sum;
02970 }
02971 
02972 
02973 static int send_raw(const char *buf, int buf_len, union sockaddr_union *to,
02974                      const unsigned int s_ip, const unsigned int s_port)
02975 {
02976    struct ip *ip;
02977    struct udphdr *udp;
02978    unsigned char packet[50];
02979    int len = sizeof(struct ip) + sizeof(struct udphdr) + buf_len;
02980 
02981    if (len > sizeof(packet)) {
02982       LM_ERR("payload too big\n");
02983       return -1;
02984    }
02985 
02986    ip = (struct ip*) packet;
02987    udp = (struct udphdr *) (packet + sizeof(struct ip));
02988    memcpy(packet + sizeof(struct ip) + sizeof(struct udphdr), buf, buf_len);
02989 
02990    ip->ip_v = 4;
02991    ip->ip_hl = sizeof(struct ip) / 4; // no options
02992    ip->ip_tos = 0;
02993    ip->ip_len = htons(len);
02994    ip->ip_id = 23;
02995    ip->ip_off = 0;
02996    ip->ip_ttl = 69;
02997    ip->ip_p = 17;
02998    ip->ip_src.s_addr = s_ip;
02999    ip->ip_dst.s_addr = to->sin.sin_addr.s_addr;
03000 
03001    ip->ip_sum = raw_checksum((unsigned char *) ip, sizeof(struct ip));
03002 
03003    udp->uh_sport = htons(s_port);
03004    udp->uh_dport = to->sin.sin_port;
03005    udp->uh_ulen = htons((unsigned short) sizeof(struct udphdr) + buf_len);
03006    udp->uh_sum = 0;
03007 
03008    return sendto(raw_sock, packet, len, 0, (struct sockaddr *) to, sizeof(struct sockaddr_in));
03009 }
03010 
03011 
03012 static void
03013 nh_timer(unsigned int ticks, void *timer_idx)
03014 {
03015    static unsigned int iteration = 0;
03016    int rval;
03017    void *buf, *cp;
03018    str c;
03019    str opt;
03020    str path;
03021    struct sip_uri curi;
03022    union sockaddr_union to;
03023    struct hostent* he;
03024    struct socket_info* send_sock;
03025    unsigned int flags;
03026    unsigned short proto;
03027 
03028    if((*natping_state) == 0)
03029       goto done;
03030 
03031    buf = NULL;
03032    if (cblen > 0) {
03033       buf = pkg_malloc(cblen);
03034       if (buf == NULL) {
03035          LM_ERR("out of pkg memory\n");
03036          goto done;
03037       }
03038    }
03039    rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only?ul.nat_flag:0),
03040       ((unsigned int)(unsigned long)timer_idx)*natping_interval+iteration,
03041       natping_processes*natping_interval);
03042    if (rval<0) {
03043       LM_ERR("failed to fetch contacts\n");
03044       goto done;
03045    }
03046    if (rval > 0) {
03047       if (buf != NULL)
03048          pkg_free(buf);
03049       cblen = rval * 2;
03050       buf = pkg_malloc(cblen);
03051       if (buf == NULL) {
03052          LM_ERR("out of pkg memory\n");
03053          goto done;
03054       }
03055       rval = ul.get_all_ucontacts(buf,cblen,(ping_nated_only?ul.nat_flag:0),
03056          ((unsigned int)(unsigned long)timer_idx)*natping_interval+iteration,
03057          natping_processes*natping_interval);
03058       if (rval != 0) {
03059          pkg_free(buf);
03060          goto done;
03061       }
03062    }
03063 
03064    if (buf == NULL)
03065       goto done;
03066 
03067    cp = buf;
03068    while (1) {
03069       memcpy(&(c.len), cp, sizeof(c.len));
03070       if (c.len == 0)
03071          break;
03072       c.s = (char*)cp + sizeof(c.len);
03073       cp =  (char*)cp + sizeof(c.len) + c.len;
03074       memcpy( &send_sock, cp, sizeof(send_sock));
03075       cp = (char*)cp + sizeof(send_sock);
03076       memcpy( &flags, cp, sizeof(flags));
03077       cp = (char*)cp + sizeof(flags);
03078       memcpy( &(path.len), cp, sizeof(path.len));
03079       path.s = path.len ? ((char*)cp + sizeof(path.len)) : NULL ;
03080       cp =  (char*)cp + sizeof(path.len) + path.len;
03081 
03082       /* determin the destination */
03083       if ( path.len && (flags&sipping_flag)!=0 ) {
03084          /* send to first URI in path */
03085          if (get_path_dst_uri( &path, &opt) < 0) {
03086             LM_ERR("failed to get dst_uri for Path\n");
03087             continue;
03088          }
03089          /* send to the contact/received */
03090          if (parse_uri(opt.s, opt.len, &curi) < 0) {
03091             LM_ERR("can't parse contact dst_uri\n");
03092             continue;
03093          }
03094       } else {
03095          /* send to the contact/received */
03096          if (parse_uri(c.s, c.len, &curi) < 0) {
03097             LM_ERR("can't parse contact uri\n");
03098             continue;
03099          }
03100       }
03101       if (curi.proto != PROTO_UDP && curi.proto != PROTO_NONE)
03102          continue;
03103       if (curi.port_no == 0)
03104          curi.port_no = SIP_PORT;
03105       proto = curi.proto;
03106       /* we sholud get rid of this resolve (to ofen and to slow); for the
03107        * moment we are lucky since the curi is an IP -bogdan */
03108       he = sip_resolvehost(&curi.host, &curi.port_no, &proto, 0, 0);
03109       if (he == NULL){
03110          LM_ERR("can't resolve_host\n");
03111          continue;
03112       }
03113       hostent2su(&to, he, 0, curi.port_no);
03114       if (send_sock==0) {
03115          send_sock=force_socket ? force_socket : 
03116                get_send_socket(0, &to, PROTO_UDP);
03117       }
03118       if (send_sock == NULL) {
03119          LM_ERR("can't get sending socket\n");
03120          continue;
03121       }
03122       if ( (flags&sipping_flag)!=0 &&
03123       (opt.s=build_sipping( &c, send_sock, &path, &opt.len))!=0 ) {
03124          if (udp_send(send_sock, opt.s, opt.len, &to)<0){
03125             LM_ERR("sip udp_send failed\n");
03126          }
03127       } else if (raw_ip) {
03128          if (send_raw((char*)sbuf, sizeof(sbuf), &to, raw_ip, raw_port)<0) {
03129             LM_ERR("send_raw failed\n");
03130          }
03131       } else {
03132          if (udp_send(send_sock, (char *)sbuf, sizeof(sbuf), &to)<0 ) {
03133             LM_ERR("udp_send failed\n");
03134          }
03135       }
03136    }
03137    pkg_free(buf);
03138 done:
03139    iteration++;
03140    if (iteration==natping_interval)
03141       iteration = 0;
03142 }
03143 
03144 
03145 /*
03146  * Create received SIP uri that will be either
03147  * passed to registrar in an AVP or apended
03148  * to Contact header field as a parameter
03149  */
03150 static int
03151 create_rcv_uri(str* uri, struct sip_msg* m)
03152 {
03153    static char buf[MAX_URI_SIZE];
03154    char* p;
03155    str ip, port;
03156    int len;
03157    str proto;
03158 
03159    if (!uri || !m) {
03160       LM_ERR("invalid parameter value\n");
03161       return -1;
03162    }
03163 
03164    ip.s = ip_addr2a(&m->rcv.src_ip);
03165    ip.len = strlen(ip.s);
03166 
03167    port.s = int2str(m->rcv.src_port, &port.len);
03168 
03169    switch(m->rcv.proto) {
03170    case PROTO_NONE:
03171    case PROTO_UDP:
03172       proto.s = 0; /* Do not add transport parameter, UDP is default */
03173       proto.len = 0;
03174       break;
03175 
03176    case PROTO_TCP:
03177       proto.s = "TCP";
03178       proto.len = 3;
03179       break;
03180 
03181    case PROTO_TLS:
03182       proto.s = "TLS";
03183       proto.len = 3;
03184       break;
03185 
03186    case PROTO_SCTP:
03187       proto.s = "SCTP";
03188       proto.len = 4;
03189       break;
03190 
03191    default:
03192       LM_ERR("unknown transport protocol\n");
03193       return -1;
03194    }
03195 
03196    len = 4 + ip.len + 2*(m->rcv.src_ip.af==AF_INET6)+ 1 + port.len;
03197    if (proto.s) {
03198       len += TRANSPORT_PARAM_LEN;
03199       len += proto.len;
03200    }
03201 
03202    if (len > MAX_URI_SIZE) {
03203       LM_ERR("buffer too small\n");
03204       return -1;
03205    }
03206 
03207    p = buf;
03208    memcpy(p, "sip:", 4);
03209    p += 4;
03210    
03211    if (m->rcv.src_ip.af==AF_INET6)
03212       *p++ = '[';
03213    memcpy(p, ip.s, ip.len);
03214    p += ip.len;
03215    if (m->rcv.src_ip.af==AF_INET6)
03216       *p++ = ']';
03217 
03218    *p++ = ':';
03219    
03220    memcpy(p, port.s, port.len);
03221    p += port.len;
03222 
03223    if (proto.s) {
03224       memcpy(p, TRANSPORT_PARAM, TRANSPORT_PARAM_LEN);
03225       p += TRANSPORT_PARAM_LEN;
03226 
03227       memcpy(p, proto.s, proto.len);
03228       p += proto.len;
03229    }
03230 
03231    uri->s = buf;
03232    uri->len = len;
03233 
03234    return 0;
03235 }
03236 
03237 
03238 /*
03239  * Add received parameter to Contacts for further
03240  * forwarding of the REGISTER requuest
03241  */
03242 static int
03243 add_rcv_param_f(struct sip_msg* msg, char* str1, char* str2)
03244 {
03245    contact_t* c;
03246    struct lump* anchor;
03247    char* param;
03248    str uri;
03249    int hdr_param;
03250 
03251    hdr_param = str1?0:1;
03252 
03253    if (create_rcv_uri(&uri, msg) < 0) {
03254       return -1;
03255    }
03256 
03257    if (contact_iterator(&c, msg, 0) < 0) {
03258       return -1;
03259    }
03260 
03261    while(c) {
03262       param = (char*)pkg_malloc(RECEIVED_LEN + 2 + uri.len);
03263       if (!param) {
03264          LM_ERR("no pkg memory left\n");
03265          return -1;
03266       }
03267       memcpy(param, RECEIVED, RECEIVED_LEN);
03268       param[RECEIVED_LEN] = '\"';
03269       memcpy(param + RECEIVED_LEN + 1, uri.s, uri.len);
03270       param[RECEIVED_LEN + 1 + uri.len] = '\"';
03271 
03272       if (hdr_param) {
03273          /* add the param as header param */
03274          anchor = anchor_lump(msg, c->name.s + c->len - msg->buf, 0, 0);
03275       } else {
03276          /* add the param as uri param */
03277          anchor = anchor_lump(msg, c->uri.s + c->uri.len - msg->buf, 0, 0);
03278       }
03279       if (anchor == NULL) {
03280          LM_ERR("anchor_lump failed\n");
03281          return -1;
03282       }     
03283 
03284       if (insert_new_lump_after(anchor, param, RECEIVED_LEN + 1 + uri.len + 1, 0) == 0) {
03285          LM_ERR("insert_new_lump_after failed\n");
03286          pkg_free(param);
03287          return -1;
03288       }
03289 
03290       if (contact_iterator(&c, msg, c) < 0) {
03291          return -1;
03292       }
03293    }
03294 
03295    return 1;
03296 }
03297 
03298 
03299 static int start_recording_f(struct sip_msg* msg, char *foo, char *bar)
03300 {
03301    int nitems;
03302    str callid = {0, 0};
03303    str from_tag = {0, 0};
03304    str to_tag = {0, 0};
03305    struct rtpp_node *node;
03306    struct iovec v[1 + 4 + 3] = {{NULL, 0}, {"R", 1}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}, {" ", 1}, {NULL, 0}};
03307                                 /* 1 */   /* 2 */   /* 3 */    /* 4 */   /* 5 */    /* 6 */   /* 1 */
03308 
03309    if (get_callid(msg, &callid) == -1 || callid.len == 0) {
03310       LM_ERR("can't get Call-Id field\n");
03311       return -1;
03312    }
03313 
03314    if (get_to_tag(msg, &to_tag) == -1) {
03315       LM_ERR("can't get To tag\n");
03316       return -1;
03317    }
03318 
03319    if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
03320       LM_ERR("can't get From tag\n");
03321       return -1;
03322    }
03323 
03324    if(msg->id != current_msg_id){
03325       selected_rtpp_set = default_rtpp_set;
03326    }
03327 
03328    STR2IOVEC(callid, v[3]);
03329    STR2IOVEC(from_tag, v[5]);
03330    STR2IOVEC(to_tag, v[7]);
03331    node = select_rtpp_node(callid, 1);
03332    if (!node) {
03333       LM_ERR("no available proxies\n");
03334       return -1;
03335    }
03336 
03337    nitems = 8;
03338    if (msg->first_line.type == SIP_REPLY) {
03339       if (to_tag.len == 0)
03340          return -1;
03341       STR2IOVEC(to_tag, v[5]);
03342       STR2IOVEC(from_tag, v[7]);
03343    } else {
03344       STR2IOVEC(from_tag, v[5]);
03345       STR2IOVEC(to_tag, v[7]);
03346       if (to_tag.len <= 0)
03347          nitems = 6;
03348    }
03349    send_rtpp_command(node, v, nitems);
03350 
03351    return 1;
03352 }
03353 
03354 
03355 
03356 /*
03357  * Create an AVP to be used by registrar with the source IP and port
03358  * of the REGISTER
03359  */
03360 static int
03361 fix_nated_register_f(struct sip_msg* msg, char* str1, char* str2)
03362 {
03363    str uri;
03364    int_str val;
03365 
03366    if(rcv_avp_name.n==0)
03367       return 1;
03368 
03369    if (create_rcv_uri(&uri, msg) < 0) {
03370       return -1;
03371    }
03372 
03373    val.s = uri;
03374 
03375    if (add_avp(AVP_VAL_STR|rcv_avp_type, rcv_avp_name, val) < 0) {
03376       LM_ERR("failed to create AVP\n");
03377       return -1;
03378    }
03379 
03380    return 1;
03381 }

Generated on Wed May 23 20:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6