00001 /* 00002 * $Id: nat_helper.c 566 2008-06-05 12:55:00Z vingarzan $ 00003 * 00004 * 00005 * Copyright (C) 2005 Porta Software Ltd. 00006 * 00007 * This file is part of ser, a free SIP server. 00008 * 00009 * ser is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version 00013 * 00014 * For a license to use the ser software under conditions 00015 * other than those described here, or to purchase support for this 00016 * software, please contact iptel.org by e-mail at the following addresses: 00017 * info@iptel.org 00018 * 00019 * ser is distributed in the hope that it will be useful, 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 * GNU General Public License for more details. 00023 * 00024 * You should have received a copy of the GNU General Public License 00025 * along with this program; if not, write to the Free Software 00026 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00027 * History: 00028 * --------- 00029 * 2003-10-09 nat_uac_test introduced (jiri) 00030 * 00031 * 2003-11-06 nat_uac_test permitted from onreply_route (jiri) 00032 * 00033 * 2003-12-01 unforce_rtp_proxy introduced (sobomax) 00034 * 00035 * 2004-01-07 RTP proxy support updated to support new version of the 00036 * RTP proxy (20040107). 00037 * 00038 * force_rtp_proxy() now inserts a special flag 00039 * into the SDP body to indicate that this session already 00040 * proxied and ignores sessions with such flag. 00041 * 00042 * Added run-time check for version of command protocol 00043 * supported by the RTP proxy. 00044 * 00045 * 2004-01-16 Integrated slightly modified patch from Tristan Colgate, 00046 * force_rtp_proxy function with IP as a parameter (janakj) 00047 * 00048 * 2004-01-28 nat_uac_test extended to allow testing SDP body (sobomax) 00049 * 00050 * nat_uac_test extended to allow testing top Via (sobomax) 00051 * 00052 * 2004-02-21 force_rtp_proxy now accepts option argument, which 00053 * consists of string of chars, each of them turns "on" 00054 * some feature, currently supported ones are: 00055 * 00056 * `a' - flags that UA from which message is received 00057 * doesn't support symmetric RTP; 00058 * `l' - force "lookup", that is, only rewrite SDP when 00059 * corresponding session is already exists in the 00060 * RTP proxy. Only makes sense for SIP requests, 00061 * replies are always processed in "lookup" mode; 00062 * `i' - flags that message is received from UA in the 00063 * LAN. Only makes sense when RTP proxy is running 00064 * in the bridge mode. 00065 * 00066 * force_rtp_proxy can now be invoked without any arguments, 00067 * as previously, with one argument - in this case argument 00068 * is treated as option string and with two arguments, in 00069 * which case 1st argument is option string and the 2nd 00070 * one is IP address which have to be inserted into 00071 * SDP (IP address on which RTP proxy listens). 00072 * 00073 * 2004-03-12 Added support for IPv6 addresses in SDPs. Particularly, 00074 * force_rtp_proxy now can work with IPv6-aware RTP proxy, 00075 * replacing IPv4 address in SDP with IPv6 one and vice versa. 00076 * This allows creating full-fledged IPv4<->IPv6 gateway. 00077 * See 4to6.cfg file for example. 00078 * 00079 * Two new options added into force_rtp_proxy: 00080 * 00081 * `f' - instructs nathelper to ignore marks inserted 00082 * by another nathelper in transit to indicate 00083 * that the session is already goes through another 00084 * proxy. Allows creating chain of proxies. 00085 * `r' - flags that IP address in SDP should be trusted. 00086 * Without this flag, nathelper ignores address in the 00087 * SDP and uses source address of the SIP message 00088 * as media address which is passed to the RTP proxy. 00089 * 00090 * Protocol between nathelper and RTP proxy in bridge 00091 * mode has been slightly changed. Now RTP proxy expects SER 00092 * to provide 2 flags when creating or updating session 00093 * to indicate direction of this session. Each of those 00094 * flags can be either `e' or `i'. For example `ei' means 00095 * that we received INVITE from UA on the "external" network 00096 * network and will send it to the UA on "internal" one. 00097 * Also possible `ie' (internal->external), `ii' 00098 * (internal->internal) and `ee' (external->external). See 00099 * example file alg.cfg for details. 00100 * 00101 * 2004-03-15 If the rtp proxy test failed (wrong version or not started) 00102 * retry test from time to time, when some *rtpproxy* function 00103 * is invoked. Minimum interval between retries can be 00104 * configured via rtpproxy_disable_tout module parameter (default 00105 * is 60 seconds). Setting it to -1 will disable periodic 00106 * rechecks completely, setting it to 0 will force checks 00107 * for each *rtpproxy* function call. (andrei) 00108 * 00109 * 2004-03-22 Fix assignment of rtpproxy_retr and rtpproxy_tout module 00110 * parameters. 00111 * 00112 * 2004-03-22 Fix get_body position (should be called before get_callid) 00113 * (andrei) 00114 * 00115 * 2004-03-24 Fix newport for null ip address case (e.g onhold re-INVITE) 00116 * (andrei) 00117 * 00118 * 2004-09-30 added received port != via port test (andrei) 00119 * 00120 * 2004-10-10 force_socket option introduced (jiri) 00121 * 00122 * 2005-02-24 Added support for using more than one rtp proxy, in which 00123 * case traffic will be distributed evenly among them. In addition, 00124 * each such proxy can be assigned a weight, which will specify 00125 * which share of the traffic should be placed to this particular 00126 * proxy. 00127 * 00128 * Introduce failover mechanism, so that if SER detects that one 00129 * of many proxies is no longer available it temporarily decreases 00130 * its weight to 0, so that no traffic will be assigned to it. 00131 * Such "disabled" proxies are periodically checked to see if they 00132 * are back to normal in which case respective weight is restored 00133 * resulting in traffic being sent to that proxy again. 00134 * 00135 * Those features can be enabled by specifying more than one "URI" 00136 * in the rtpproxy_sock parameter, optionally followed by the weight, 00137 * which if absent is assumed to be 1, for example: 00138 * 00139 * rtpproxy_sock="unix:/foo/bar=4 udp:1.2.3.4:3456=3 udp:5.6.7.8:5432=1" 00140 * 00141 * 2005-02-25 Force for pinging the socket returned by USRLOC (bogdan) 00142 * 00143 * 2005-03-22 Support for multiple media streams added (netch) 00144 * 00145 * 2005-04-27 Support for doing natpinging using real SIP requests added. 00146 * Requires tm module for doing its work. Old method (sending UDP 00147 * with 4 zero bytes can be selected by specifying natping_method="null". 00148 * 00149 * 2005-12-23 Support for selecting particular RTP proxy node has been added. 00150 * In force_rtp_proxy() it can be done via new N modifier, followed 00151 * by the index (starting at 0) of the node in the rtpproxy_sock 00152 * parameter. For example, in the example above force_rtp_proxy("N1") will 00153 * will select node udp:1.2.3.4:3456. In unforce_rtp_proxy(), the same 00154 * can be done by specifying index as an argument directly, i.e. 00155 * unforce_rtp_proxy(1). 00156 * 00157 * Since nathelper is not transaction or call stateful, care should be 00158 * taken to ensure that force_rtp_proxy() in request path matches 00159 * force_rtp_proxy() in reply path, that is the same node is selected. 00160 * 00161 * 2006-06-10 select nathepler.rewrite_contact 00162 * pingcontact function (tma) 00163 */ 00164 00221 #include <stdio.h> 00222 #include <stdlib.h> 00223 #include <string.h> 00224 #include <sys/socket.h> 00225 #include <netinet/in.h> 00226 #include <arpa/inet.h> 00227 00228 #include "../../parser/msg_parser.h" 00229 #include "../../msg_translator.h" 00230 #include "../../parser/parser_f.h" 00231 #include "../../parser/contact/contact.h" 00232 #include "../../parser/contact/parse_contact.h" 00233 #include "../../parser/parse_uri.h" 00234 #include "../../parser/hf.h" 00235 #include "../../ut.h" 00236 #include "../../forward.h" 00237 #include "mod.h" 00238 #include "registrar_storage.h" 00239 #include "nat_helper.h" 00240 00241 static const char udp_ping[2] = { 10, 13}; 00243 extern int pcscf_nat_enable; 00244 extern int pcscf_nat_ping; 00245 extern int pcscf_nat_pingall; 00246 extern int pcscf_nat_detection_type; 00248 #define READ(val) \ 00249 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24)) 00250 #define advance(_ptr,_n,_str,_error) \ 00251 do{\ 00252 if ((_ptr)+(_n)>(_str).s+(_str).len)\ 00253 goto _error;\ 00254 (_ptr) = (_ptr) + (_n);\ 00255 }while(0); 00256 #define one_of_16( _x , _t ) \ 00257 (_x==_t[0]||_x==_t[15]||_x==_t[8]||_x==_t[2]||_x==_t[3]||_x==_t[4]\ 00258 ||_x==_t[5]||_x==_t[6]||_x==_t[7]||_x==_t[1]||_x==_t[9]||_x==_t[10]\ 00259 ||_x==_t[11]||_x==_t[12]||_x==_t[13]||_x==_t[14]) 00260 #define one_of_8( _x , _t ) \ 00261 (_x==_t[0]||_x==_t[7]||_x==_t[1]||_x==_t[2]||_x==_t[3]||_x==_t[4]\ 00262 ||_x==_t[5]||_x==_t[6]) 00263 00264 00265 network_t nets_1918[] = { 00266 {"10.0.0.0", 0, 0xffffffffu << 24}, 00267 {"172.16.0.0", 0, 0xffffffffu << 20}, 00268 {"192.168.0.0", 0, 0xffffffffu << 16}, 00269 {NULL, 0, 0} 00270 }; 00271 00272 00278 int is1918addr(str *saddr) { 00279 struct in_addr addr; 00280 uint32_t netaddr; 00281 int i, rval; 00282 char backup; 00283 00284 rval = -1; 00285 backup = saddr->s[saddr->len]; 00286 saddr->s[saddr->len] = '\0'; 00287 if (inet_aton(saddr->s, &addr) != 1) 00288 goto is1918addr_end; 00289 netaddr = ntohl(addr.s_addr); 00290 for (i = 0; nets_1918[i].cnetaddr != NULL; i++) { 00291 if ((netaddr & nets_1918[i].mask) == nets_1918[i].netaddr) { 00292 rval = 1; 00293 goto is1918addr_end; 00294 } 00295 } 00296 rval = 0; 00297 00298 is1918addr_end: 00299 saddr->s[saddr->len] = backup; 00300 return rval; 00301 } 00302 00303 00309 char * ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2) 00310 { 00311 /* Initialize search pointer */ 00312 char *sp = (char *) b1; 00313 00314 /* Initialize pattern pointer */ 00315 char *pp = (char *) b2; 00316 00317 /* Initialize end of search address space pointer */ 00318 char *eos = sp + len1 - len2; 00319 00320 /* Sanity check */ 00321 if(!(b1 && b2 && len1 && len2)) 00322 return NULL; 00323 00324 while (sp <= eos) { 00325 if (*sp == *pp) 00326 if (memcmp(sp, pp, len2) == 0) 00327 return sp; 00328 00329 sp++; 00330 } 00331 00332 return NULL; 00333 } 00334 00338 int nat_prepare_1918addr() { 00339 int i; 00340 struct in_addr addr; 00341 00342 /* Prepare 1918 networks list */ 00343 for (i = 0; nets_1918[i].cnetaddr != NULL; i++) { 00344 if (inet_aton(nets_1918[i].cnetaddr, &addr) != 1) 00345 abort(); 00346 nets_1918[i].netaddr = ntohl(addr.s_addr) & nets_1918[i].mask; 00347 } 00348 return 1; 00349 } 00350 00358 static inline int get_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c) 00359 { 00360 00361 if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact) 00362 return -1; 00363 if (!_m->contact->parsed && parse_contact(_m->contact) < 0) { 00364 LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n"); 00365 return -1; 00366 } 00367 *_c = ((contact_body_t*)_m->contact->parsed)->contacts; 00368 if (*_c == NULL) { 00369 LOG(L_DBG, "get_contact_uri: Error while parsing Contact body or star contact\n"); 00370 return -1; 00371 } 00372 if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) { 00373 LOG(L_ERR, "get_contact_uri: Error while parsing Contact URI\n"); 00374 return -1; 00375 } 00376 return 0; 00377 } 00378 00380 // * Checks if the contact in the message is a 1918 address 00381 // * @param msg - the SIP message 00382 // * @returns 1 if it is, 0 if not, -1 on not found 00383 // */ 00384 //static int contact_1918(struct sip_msg * msg) { 00385 // struct sip_uri uri; 00386 // contact_t * c; 00387 // 00388 // if(get_contact_uri(msg, &uri, &c) == -1) 00389 // return -1; 00390 // 00391 // return (is1918addr(&(uri.host)) == 1)?1:0; 00392 //} 00393 00399 static int via_1918(struct sip_msg * msg) { 00400 return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0; 00401 } 00402 00408 int nat_uac_test(struct sip_msg * msg) { 00409 00410 if(pcscf_nat_pingall) 00411 return 1; 00412 00413 if((pcscf_nat_detection_type && NAT_UAC_TEST_RPORT) && 00414 (msg->rcv.src_port != (msg-> via1->port ? msg->via1->port:SIP_PORT))) 00415 return 1; 00416 00417 if((pcscf_nat_detection_type & NAT_UAC_TEST_RCVD) && received_test(msg)) 00418 return 1; 00419 00420 // if((pcscf_nat_detection_type & NAT_UAC_TEST_C_1918) && contact_1918(msg)) 00421 //return 1; 00422 00423 // if((pcscf_nat_detection_type & NAT_UAC_TEST_S_1918) && sdp_1918(msg)) 00424 // return 1; 00425 00426 if((pcscf_nat_detection_type & NAT_UAC_TEST_V_1918) && via_1918(msg)) 00427 return 1; 00428 00429 return 0; 00430 } 00431 00438 r_nat_dest* nat_msg_origin(struct sip_msg * msg) { 00439 r_nat_dest *pinhole=NULL; 00440 if (!pcscf_nat_enable) return NULL; 00441 if(pcscf_nat_pingall || nat_uac_test(msg)) { 00442 pinhole = shm_malloc(sizeof(r_nat_dest)); 00443 if (pinhole == NULL) { 00444 LOG(L_ERR,"ERR:"M_NAME":nat_msg_origin:no memory\n"); 00445 return NULL; 00446 } 00447 memcpy(&pinhole->nat_addr, &msg->rcv.src_ip, sizeof(struct ip_addr)); 00448 pinhole -> nat_port = msg -> rcv.src_port; 00449 } 00450 return pinhole; 00451 } 00452 00458 int requires_nat(struct sip_msg * msg) 00459 { 00460 return pcscf_nat_enable && (pcscf_nat_pingall || nat_uac_test(msg)); 00461 } 00462 00463 00469 int nat_send_ping(r_contact *c) { 00470 struct dest_info dst; 00471 00472 if(c->pinhole == NULL) 00473 return 1; 00474 if(c->transport != PROTO_UDP && c->transport != PROTO_NONE) 00475 return 1; 00476 init_dest_info(&dst); 00477 dst.proto = PROTO_UDP; 00478 00479 memset(&(dst.to), 0, sizeof(union sockaddr_union)); 00480 dst.to.s.sa_family=c->pinhole->nat_addr.af; 00481 switch(dst.to.s.sa_family) { 00482 case AF_INET6: 00483 memcpy(&dst.to.sin6.sin6_addr, c->pinhole->nat_addr.u.addr, c->pinhole->nat_addr.len); 00484 //dst.to.sin6.sin6_len=sizeof(struct sockaddr_in6); 00485 dst.to.sin6.sin6_port=htons(c->pinhole->nat_port); 00486 break; 00487 case AF_INET: 00488 memcpy(&dst.to.sin.sin_addr, c->pinhole->nat_addr.u.addr, c->pinhole->nat_addr.len); 00489 //dst.to.sin.sin_len=sizeof(struct sockaddr_in); 00490 dst.to.sin.sin_port=htons(c->pinhole->nat_port); 00491 break; 00492 default: 00493 LOG(L_CRIT,"CRIT:"M_NAME":nat_send_ping: unknown address family %d\n", dst.to.s.sa_family); 00494 return -1; 00495 } 00496 dst.send_sock=get_send_socket(0, &dst.to, PROTO_UDP); 00497 if(dst.send_sock == NULL) { 00498 LOG(L_ERR,"ERR:"M_NAME":nat_send_ping: cannot get sending socket\n"); 00499 return -1; 00500 } 00501 udp_send(&dst, (char *)udp_ping, sizeof(udp_ping)); 00502 return 1; 00503 }
1.5.2