⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nathelper.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: nathelper.c,v 1.21 2006/06/07 13:52:44 bogdan_iancu Exp $ * * Copyright (C) 2003 Porta Software Ltd * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * History: * --------- * 2003-10-09	nat_uac_test introduced (jiri) * * 2003-11-06   nat_uac_test permitted from onreply_route (jiri) * * 2003-12-01   unforce_rtp_proxy introduced (sobomax) * * 2004-01-07	RTP proxy support updated to support new version of the *		RTP proxy (20040107). * *		force_rtp_proxy() now inserts a special flag *		into the SDP body to indicate that this session already *		proxied and ignores sessions with such flag. * *		Added run-time check for version of command protocol *		supported by the RTP proxy. * * 2004-01-16   Integrated slightly modified patch from Tristan Colgate, *		force_rtp_proxy function with IP as a parameter (janakj) * * 2004-01-28	nat_uac_test extended to allow testing SDP body (sobomax) * *		nat_uac_test extended to allow testing top Via (sobomax) * * 2004-02-21	force_rtp_proxy now accepts option argument, which *		consists of string of chars, each of them turns "on" *		some feature, currently supported ones are: * *		 `a' - flags that UA from which message is received *		       doesn't support symmetric RTP; *		 `l' - force "lookup", that is, only rewrite SDP when *		       corresponding session is already exists in the *		       RTP proxy. Only makes sense for SIP requests, *		       replies are always processed in "lookup" mode; *		 `i' - flags that message is received from UA in the *		       LAN. Only makes sense when RTP proxy is running *		       in the bridge mode. * *		force_rtp_proxy can now be invoked without any arguments, *		as previously, with one argument - in this case argument *		is treated as option string and with two arguments, in *		which case 1st argument is option string and the 2nd *		one is IP address which have to be inserted into *		SDP (IP address on which RTP proxy listens). * * 2004-03-12	Added support for IPv6 addresses in SDPs. Particularly, *		force_rtp_proxy now can work with IPv6-aware RTP proxy, *		replacing IPv4 address in SDP with IPv6 one and vice versa. *		This allows creating full-fledged IPv4<->IPv6 gateway. *		See 4to6.cfg file for example. * *		Two new options added into force_rtp_proxy: * *		 `f' - instructs nathelper to ignore marks inserted *		       by another nathelper in transit to indicate *		       that the session is already goes through another *		       proxy. Allows creating chain of proxies. *		 `r' - flags that IP address in SDP should be trusted. *		       Without this flag, nathelper ignores address in the *		       SDP and uses source address of the SIP message *		       as media address which is passed to the RTP proxy. * *		Protocol between nathelper and RTP proxy in bridge *		mode has been slightly changed. Now RTP proxy expects SER *		to provide 2 flags when creating or updating session *		to indicate direction of this session. Each of those *		flags can be either `e' or `i'. For example `ei' means *		that we received INVITE from UA on the "external" network *		network and will send it to the UA on "internal" one. *		Also possible `ie' (internal->external), `ii' *		(internal->internal) and `ee' (external->external). See *		example file alg.cfg for details. * * 2004-03-15	If the rtp proxy test failed (wrong version or not started) *		retry test from time to time, when some *rtpproxy* function *		is invoked. Minimum interval between retries can be *		configured via rtpproxy_disable_tout module parameter (default *		is 60 seconds). Setting it to -1 will disable periodic *		rechecks completely, setting it to 0 will force checks *		for each *rtpproxy* function call. (andrei) * * 2004-03-22	Fix assignment of rtpproxy_retr and rtpproxy_tout module *		parameters. * * 2004-03-22	Fix get_body position (should be called before get_callid) * 				(andrei) * * 2004-03-24	Fix newport for null ip address case (e.g onhold re-INVITE) * 				(andrei) * * 2004-09-30	added received port != via port test (andrei) * * 2004-10-10   force_socket option introduced (jiri) * * 2005-02-24	Added support for using more than one rtp proxy, in which *		case traffic will be distributed evenly among them. In addition, *		each such proxy can be assigned a weight, which will specify *		which share of the traffic should be placed to this particular *		proxy. * *		Introduce failover mechanism, so that if SER detects that one *		of many proxies is no longer available it temporarily decreases *		its weight to 0, so that no traffic will be assigned to it. *		Such "disabled" proxies are periodically checked to see if they *		are back to normal in which case respective weight is restored *		resulting in traffic being sent to that proxy again. * *		Those features can be enabled by specifying more than one "URI" *		in the rtpproxy_sock parameter, optionally followed by the weight, *		which if absent is assumed to be 1, for example: * *		rtpproxy_sock="unix:/foo/bar=4 udp:1.2.3.4:3456=3 udp:5.6.7.8:5432=1" * * 2005-02-25	Force for pinging the socket returned by USRLOC (bogdan) * * 2005-03-22	support for multiple media streams added (netch) * * 2005-07-11  SIP ping support added (bogdan) * * 2005-07-14  SDP origin (o=) IP may be also changed (bogdan) * * 2006-03-08  fix_nated_sdp() may take one more param to force a specific IP; *             force_rtp_proxy() accepts a new flag 's' to swap creation/ *              confirmation between requests/replies;  *             add_rcv_param() may take as parameter a flag telling if the *              parameter should go to the contact URI or contact header; *             (bogdan) * 2006-03-28 Support for changing session-level SDP connection (c=) IP when *            media-description also includes connection information (bayan) */#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/uio.h>#include <sys/un.h>#include <ctype.h>#include <errno.h>#include <netdb.h>#include <poll.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "../../flags.h"#include "../../sr_module.h"#include "../../dprint.h"#include "../../data_lump.h"#include "../../data_lump_rpl.h"#include "../../error.h"#include "../../forward.h"#include "../../mem/mem.h"#include "../../parser/parse_from.h"#include "../../parser/parse_to.h"#include "../../parser/parse_uri.h"#include "../../parser/parser_f.h"#include "../../resolve.h"#include "../../timer.h"#include "../../trim.h"#include "../../ut.h"#include "../../items.h"#include "../../msg_translator.h"#include "../../usr_avp.h"#include "../../socket_info.h"#include "../registrar/sip_msg.h"#include "../usrloc/usrloc.h"#include "nhelpr_funcs.h"#include "sip_pinger.h" MODULE_VERSION#if !defined(AF_LOCAL)#define	AF_LOCAL AF_UNIX#endif#if !defined(PF_LOCAL)#define	PF_LOCAL PF_UNIX#endif/* NAT UAC test constants */#define	NAT_UAC_TEST_C_1918	0x01#define	NAT_UAC_TEST_RCVD	0x02#define	NAT_UAC_TEST_V_1918	0x04#define	NAT_UAC_TEST_S_1918	0x08#define	NAT_UAC_TEST_RPORT	0x10/* Handy macros */#define	STR2IOVEC(sx, ix)	do {(ix).iov_base = (sx).s; (ix).iov_len = (sx).len;} while(0)#define	SZ2IOVEC(sx, ix)	do {(ix).iov_base = (sx); (ix).iov_len = strlen(sx);} while(0)/* Supported version of the RTP proxy command protocol */#define	SUP_CPROTOVER	20040107/* Required additional version of the RTP proxy command protocol */#define	REQ_CPROTOVER	"20050322"#define	CPORT		"22222"struct rtpp_head;struct rtpp_node;static int nat_uac_test_f(struct sip_msg* msg, char* str1, char* str2);static int fix_nated_contact_f(struct sip_msg *, char *, char *);static int fix_nated_sdp_f(struct sip_msg *, char *, char *);static int extract_mediaip(str *, str *, int *, char *);static int extract_mediaport(str *, str *);static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);static int alter_mediaport(struct sip_msg *, str *, str *, str *, int);static char *gencookie();static int rtpp_test(struct rtpp_node*, int, int);static char *send_rtpp_command(struct rtpp_node*, struct iovec *, int);static int unforce_rtp_proxy_f(struct sip_msg *, char *, char *);static int force_rtp_proxy0_f(struct sip_msg *, char *, char *);static int force_rtp_proxy1_f(struct sip_msg *, char *, char *);static int force_rtp_proxy2_f(struct sip_msg *, char *, char *);static int fix_nated_register_f(struct sip_msg *, char *, char *);static int fixup_fix_sdp(void** param, int param_no);static int add_rcv_param_f(struct sip_msg *, char *, char *);static char *find_sdp_line(char *, char *, char);static char *find_next_sdp_line(char *, char *, char, char *);static void nh_timer(unsigned int, void *);inline static int fixup_str2int(void**, int);static int mod_init(void);static int child_init(int);static usrloc_api_t ul;static int cblen = 0;static int natping_interval = 0;struct socket_info* force_socket = 0;static struct {	const char *cnetaddr;	uint32_t netaddr;	uint32_t mask;} nets_1918[] = {	{"10.0.0.0",    0, 0xffffffffu << 24},	{"172.16.0.0",  0, 0xffffffffu << 20},	{"192.168.0.0", 0, 0xffffffffu << 16},	{NULL, 0, 0}};static str sup_ptypes[] = {	{.s = "udp", .len = 3},	{.s = "udptl", .len = 5},	{.s = "rtp/avp", .len = 7},	{.s = NULL, .len = 0}};/* * If this parameter is set then the natpinger will ping only contacts * that have the NAT flag set in user location database */static int ping_nated_only = 0;static const char sbuf[4] = {0, 0, 0, 0};static char *rtpproxy_sock = "unix:/var/run/rtpproxy.sock"; /* list */static char *force_socket_str = 0;static int rtpproxy_disable = 0;static int rtpproxy_disable_tout = 60;static int rtpproxy_retr = 5;static int rtpproxy_tout = 1;static pid_t mypid;static unsigned int myseqn = 0;static int rcv_avp_no = 42;struct rtpp_head {	struct rtpp_node	*rn_first;	struct rtpp_node	*rn_last;};struct rtpp_node {	char			*rn_url;	/* unparsed, deletable */	int			rn_umode;	char			*rn_address;	/* substring of rn_url */	int			rn_fd;		/* control fd */	int			rn_disabled;	/* found unaccessible? */	unsigned		rn_weight;	/* for load balancing */	int			rn_recheck_ticks;	struct rtpp_node	*rn_next;};/* RTP proxy balancing list */static struct rtpp_head rtpp_list;static int rtpp_node_count = 0;static cmd_export_t cmds[] = {	{"fix_nated_contact",  fix_nated_contact_f,    0, 0,			REQUEST_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE},	{"fix_nated_sdp",      fix_nated_sdp_f,        1, fixup_fix_sdp,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"fix_nated_sdp",      fix_nated_sdp_f,        2, fixup_fix_sdp,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"unforce_rtp_proxy",  unforce_rtp_proxy_f,    0, 0,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"force_rtp_proxy",    force_rtp_proxy0_f,     0, 0,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"force_rtp_proxy",    force_rtp_proxy1_f,     1, 0,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"force_rtp_proxy",    force_rtp_proxy2_f,     2, 0,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"nat_uac_test",       nat_uac_test_f,         1, fixup_str2int,			REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},	{"fix_nated_register", fix_nated_register_f,   0, 0,			REQUEST_ROUTE },	{"add_rcv_param",      add_rcv_param_f,        0, 0,			REQUEST_ROUTE },	{"add_rcv_param",      add_rcv_param_f,        1, fixup_str2int,			REQUEST_ROUTE },	{0, 0, 0, 0, 0}};static param_export_t params[] = {	{"natping_interval",      INT_PARAM, &natping_interval      },	{"ping_nated_only",       INT_PARAM, &ping_nated_only       },	{"rtpproxy_sock",         STR_PARAM, &rtpproxy_sock         },	{"rtpproxy_disable",      INT_PARAM, &rtpproxy_disable      },	{"rtpproxy_disable_tout", INT_PARAM, &rtpproxy_disable_tout },	{"rtpproxy_retr",         INT_PARAM, &rtpproxy_retr         },	{"rtpproxy_tout",         INT_PARAM, &rtpproxy_tout         },	{"received_avp",          INT_PARAM, &rcv_avp_no            },	{"force_socket",          STR_PARAM, &force_socket_str      },	{"sipping_from",          STR_PARAM, &sipping_from.s        },	{"sipping_method",        STR_PARAM, &sipping_method.s      },	{0, 0, 0}};struct module_exports exports = {	"nathelper",	cmds,	params,	0, /* exported statistics */	mod_init,	0, /* reply processing */	0, /* destroy function */	child_init};static intfixup_fix_sdp(void** param, int param_no){	xl_elem_t *model;	if (param_no==1) {		/* flags */		return fixup_str2int( param, param_no);	}	/* new IP */	model=NULL;	if(xl_parse_format((char*)(*param),&model,XL_DISABLE_COLORS)<0) {		LOG(L_ERR, "ERROR:nathelper:fixup_fix_sdp: wrong format[%s]!\n",			(char*)(*param));		return E_UNSPEC;	}	if (model==NULL) {		LOG(L_ERR, "ERROR:nathelper:fixup_fix_sdp: empty parameter!\n");		return E_UNSPEC;	}	*param = (void*)model;	return 0;}static intmod_init(void){	int i;	bind_usrloc_t bind_usrloc;	struct in_addr addr;	str socket_str;	if (force_socket_str) {		socket_str.s=force_socket_str;		socket_str.len=strlen(socket_str.s);		force_socket=grep_sock_info(&socket_str,0,0);	}	if (natping_interval > 0) {		bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);		if (!bind_usrloc) {			LOG(L_ERR, "ERROR:nathelper:mod_init: Can't find usrloc module\n");			return -1;		}		if (bind_usrloc(&ul) < 0) {			return -1;		}		/* set reply function if SIP natping is enabled */		if (sipping_from.s && sipping_from.s[0]) {			if (sipping_method.s==0 || sipping_method.s[0]==0) {				LOG(L_ERR,"ERROR:nathelper:mod_init: SIP ping FROM set, but "					"SIP ping method is empty!\n");				return -1;			}			sipping_method.len = strlen(sipping_method.s);			sipping_from.len = strlen(sipping_from.s);			exports.response_f = sipping_rpl_filter;			init_sip_ping();		} else {			sipping_from.s = 0;		}		register_timer(nh_timer, NULL, natping_interval);	}	/* Prepare 1918 networks list */	for (i = 0; nets_1918[i].cnetaddr != NULL; i++) {		if (inet_aton(nets_1918[i].cnetaddr, &addr) != 1)			abort();		nets_1918[i].netaddr = ntohl(addr.s_addr) & nets_1918[i].mask;	}	memset(&rtpp_list, 0, sizeof(rtpp_list));	rtpp_node_count = 0;	if (rtpproxy_disable == 0) {		/* Make rtp proxies list. */		char *p, *p1, *p2, *plim;		p = rtpproxy_sock;		plim = p + strlen(p);		for(;;) {			struct rtpp_node *pnode;			int weight;			weight = 1;			while (*p && isspace((int)*p))				++p;			if (p >= plim)				break;			p1 = p;			while (*p && !isspace((int)*p))				++p;			if (p <= p1)				break; /* may happen??? */			/* Have weight specified? If yes, scan it */			p2 = memchr(p1, '=', p - p1);			if (p2 != NULL) {				weight = strtoul(p2 + 1, NULL, 10);			} else {				p2 = p;			}			pnode = pkg_malloc(sizeof(struct rtpp_node));			if (pnode == NULL) {				LOG(L_ERR, "nathelper: Can't allocate memory\n");				return -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -