nathelper.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 2,354 行 · 第 1/5 页

C
2,354
字号
			}			memset(pnode, 0, sizeof(*pnode));			pnode->rn_recheck_ticks = 0;			pnode->rn_weight = weight;			pnode->rn_umode = 0;			pnode->rn_fd = -1;			pnode->rn_disabled = 0;			pnode->rn_url = pkg_malloc(p2 - p1 + 1);			if (pnode->rn_url == NULL) {				LOG(L_ERR, "nathelper: Can't allocate memory\n");				return -1;			}			memmove(pnode->rn_url, p1, p2 - p1);			pnode->rn_url[p2 - p1] = 0;			if (rtpp_list.rn_first == NULL) {				rtpp_list.rn_first = pnode;			} else {				rtpp_list.rn_last->rn_next = pnode;			}			rtpp_list.rn_last = pnode;			++rtpp_node_count;			/* Leave only address in rn_address */			pnode->rn_address = pnode->rn_url;			if (strncmp(pnode->rn_address, "udp:", 4) == 0) {				pnode->rn_umode = 1;				pnode->rn_address += 4;			} else if (strncmp(pnode->rn_address, "udp6:", 5) == 0) {				pnode->rn_umode = 6;				pnode->rn_address += 5;			} else if (strncmp(pnode->rn_address, "unix:", 5) == 0) {				pnode->rn_umode = 0;				pnode->rn_address += 5;			}		}	}	return 0;}static intchild_init(int rank){	int n;	char *cp;	struct addrinfo hints, *res;	struct rtpp_node *pnode;	/* Iterate known RTP proxies - create sockets */	mypid = getpid();	for (pnode = rtpp_list.rn_first; pnode != NULL; pnode = pnode->rn_next) {		char *old_colon;		if (pnode->rn_umode == 0)			goto rptest;		/*		 * This is UDP or UDP6. Detect host and port; lookup host;		 * do connect() in order to specify peer address		 */		old_colon = cp = strrchr(pnode->rn_address, ':');		if (cp != NULL) {			old_colon = cp;			*cp = '\0';			cp++;		}		if (cp == NULL || *cp == '\0')			cp = CPORT;		memset(&hints, 0, sizeof(hints));		hints.ai_flags = 0;		hints.ai_family = (pnode->rn_umode == 6) ? AF_INET6 : AF_INET;		hints.ai_socktype = SOCK_DGRAM;		if ((n = getaddrinfo(pnode->rn_address, cp, &hints, &res)) != 0) {			LOG(L_ERR, "nathelper: getaddrinfo: %s\n", gai_strerror(n));			return -1;		}		if (old_colon)			*old_colon = ':'; /* restore rn_address */		pnode->rn_fd = socket((pnode->rn_umode == 6)		    ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);		if (pnode->rn_fd == -1) {			LOG(L_ERR, "nathelper: can't create socket\n");			freeaddrinfo(res);			return -1;		}		if (connect(pnode->rn_fd, res->ai_addr, res->ai_addrlen) == -1) {			LOG(L_ERR, "nathelper: can't connect to a RTP proxy\n");			close(pnode->rn_fd);			pnode->rn_fd = -1;			freeaddrinfo(res);			return -1;		}		freeaddrinfo(res);rptest:		pnode->rn_disabled = rtpp_test(pnode, 0, 1);	}	if (rtpproxy_disable)		rtpproxy_disable_tout = -1;	return 0;}static intisnulladdr(str *sx, int pf){	char *cp;	if (pf == AF_INET6) {		for(cp = sx->s; cp < sx->s + sx->len; cp++)			if (*cp != '0' && *cp != ':')				return 0;		return 1;	}	return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);}/* * ser_memmem() returns the location of the first occurrence of data * pattern b2 of size len2 in memory block b1 of size len1 or * NULL if none is found. Obtained from NetBSD. */static void *ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2){	/* Initialize search pointer */	char *sp = (char *) b1;	/* Initialize pattern pointer */	char *pp = (char *) b2;	/* Initialize end of search address space pointer */	char *eos = sp + len1 - len2;	/* Sanity check */	if(!(b1 && b2 && len1 && len2))		return NULL;	while (sp <= eos) {		if (*sp == *pp)			if (memcmp(sp, pp, len2) == 0)				return sp;			sp++;	}	return NULL;}/* * Some helper functions taken verbatim from tm module. *//* * Extract tag from To header field of a response * assumes the to header is already parsed, so * make sure it really is before calling this function */static inline intget_to_tag(struct sip_msg* _m, str* _tag){	if (!_m->to) {		LOG(L_ERR, "get_to_tag(): To header field missing\n");		return -1;	}	if (get_to(_m)->tag_value.len) {		_tag->s = get_to(_m)->tag_value.s;		_tag->len = get_to(_m)->tag_value.len;	} else {		_tag->len = 0;	}	return 0;}/* * Extract tag from From header field of a request */static inline intget_from_tag(struct sip_msg* _m, str* _tag){	if (parse_from_header(_m)<0) {		LOG(L_ERR, "get_from_tag(): Error while parsing From header\n");		return -1;	}	if (get_from(_m)->tag_value.len) {		_tag->s = get_from(_m)->tag_value.s;		_tag->len = get_from(_m)->tag_value.len;	} else {		_tag->len = 0;	}	return 0;}/* * Extract Call-ID value * assumes the callid header is already parsed * (so make sure it is, before calling this function or *  it might fail even if the message _has_ a callid) */static inline intget_callid(struct sip_msg* _m, str* _cid){	if ((parse_headers(_m, HDR_CALLID_F, 0) == -1)) {		LOG(L_ERR, "get_callid(): parse_headers() failed\n");		return -1;	}	if (_m->callid == NULL) {		LOG(L_ERR, "get_callid(): Call-ID not found\n");		return -1;	}	_cid->s = _m->callid->body.s;	_cid->len = _m->callid->body.len;	trim(_cid);	return 0;}/* * Extract URI from the Contact header field */static inline intget_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c){	if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact)		return -1;	if (!_m->contact->parsed && parse_contact(_m->contact) < 0) {		LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n");		return -1;	}	*_c = ((contact_body_t*)_m->contact->parsed)->contacts;	if (*_c == NULL)		/* no contacts found */		return -1;	if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) {		LOG(L_ERR, "get_contact_uri: Error while parsing Contact URI\n");		return -1;	}	return 0;}/* * Replaces ip:port pair in the Contact: field with the source address * of the packet. */static intfix_nated_contact_f(struct sip_msg* msg, char* str1, char* str2){	int offset, len, len1;	char *cp, *buf, temp[2];	contact_t *c;	struct lump *anchor;	struct sip_uri uri;	str hostport;	if (get_contact_uri(msg, &uri, &c) == -1)		return -1;	if ((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {		LOG(L_ERR, "ERROR: you can't call fix_nated_contact twice, "		    "check your config!\n");		return -1;	}	offset = c->uri.s - msg->buf;	anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T);	if (anchor == 0)		return -1;	hostport = uri.host;	if (uri.port.len > 0)		hostport.len = uri.port.s + uri.port.len - uri.host.s;	cp = ip_addr2a(&msg->rcv.src_ip);	len = c->uri.len + strlen(cp) + 6 /* :port */ - hostport.len + 1;	buf = pkg_malloc(len);	if (buf == NULL) {		LOG(L_ERR, "ERROR: fix_nated_contact: out of memory\n");		return -1;	}	temp[0] = hostport.s[0];	temp[1] = c->uri.s[c->uri.len];	c->uri.s[c->uri.len] = hostport.s[0] = '\0';	len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->rcv.src_port,	    hostport.s + hostport.len);	if (len1 < len)		len = len1;	hostport.s[0] = temp[0];	c->uri.s[c->uri.len] = temp[1];	if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) {		pkg_free(buf);		return -1;	}	c->uri.s = buf;	c->uri.len = len;	return 1;}inline static intfixup_str2int( void** param, int param_no){	unsigned long go_to;	int err;	if (param_no == 1 || param_no == 2) {		go_to = str2s(*param, strlen(*param), &err);		if (err == 0) {			pkg_free(*param);			*param = (void *)go_to;			return 0;		} else {			LOG(L_ERR, "ERROR: fixup_str2int: bad number <%s>\n",				(char *)(*param));			return E_CFG;		}	}	return 0;}/* * Test if IP address pointed to by saddr belongs to RFC1918 networks */static inline intis1918addr(str *saddr){	struct in_addr addr;	uint32_t netaddr;	int i, rval;	char backup;	rval = -1;	backup = saddr->s[saddr->len];	saddr->s[saddr->len] = '\0';	if (inet_aton(saddr->s, &addr) != 1)		goto theend;	netaddr = ntohl(addr.s_addr);	for (i = 0; nets_1918[i].cnetaddr != NULL; i++) {		if ((netaddr & nets_1918[i].mask) == nets_1918[i].netaddr) {			rval = 1;			goto theend;		}	}	rval = 0;theend:	saddr->s[saddr->len] = backup;	return rval;}/* * test for occurrence of RFC1918 IP address in Contact HF */static intcontact_1918(struct sip_msg* msg){	struct sip_uri uri;	contact_t* c;	if (get_contact_uri(msg, &uri, &c) == -1)		return -1;	return (is1918addr(&(uri.host)) == 1) ? 1 : 0;}/* * test for occurrence of RFC1918 IP address in SDP */static intsdp_1918(struct sip_msg* msg){	str body, ip;	int pf;	if (extract_body(msg, &body) == -1) {		LOG(L_ERR,"ERROR: sdp_1918: cannot extract body from msg!\n");		return 0;	}	if (extract_mediaip(&body, &ip, &pf,"c=") == -1) {		LOG(L_ERR, "ERROR: sdp_1918: can't extract media IP from the SDP\n");		return 0;	}	if (pf != AF_INET || isnulladdr(&ip, pf))		return 0;	return (is1918addr(&ip) == 1) ? 1 : 0;}/* * test for occurrence of RFC1918 IP address in top Via */static intvia_1918(struct sip_msg* msg){	return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0;}static intnat_uac_test_f(struct sip_msg* msg, char* str1, char* str2){	int tests;	tests = (int)(long)str1;	/* return true if any of the NAT-UAC tests holds */	/* test if the source port is different from the port in Via */	if ((tests & NAT_UAC_TEST_RPORT) &&		 (msg->rcv.src_port!=(msg->via1->port?msg->via1->port:SIP_PORT)) ){		return 1;	}	/*	 * test if source address of signaling is different from	 * address advertised in Via	 */	if ((tests & NAT_UAC_TEST_RCVD) && received_test(msg))		return 1;	/*	 * test for occurrences of RFC1918 addresses in Contact	 * header field	 */	if ((tests & NAT_UAC_TEST_C_1918) && (contact_1918(msg)>0))		return 1;	/*	 * test for occurrences of RFC1918 addresses in SDP body	 */	if ((tests & NAT_UAC_TEST_S_1918) && sdp_1918(msg))		return 1;	/*	 * test for occurrences of RFC1918 addresses top Via	 */	if ((tests & NAT_UAC_TEST_V_1918) && via_1918(msg))		return 1;	/* no test succeeded */	return -1;}#define	ADD_ADIRECTION	0x01#define	FIX_MEDIP	0x02#define	ADD_ANORTPPROXY	0x04#define	FIX_ORGIP	0x08#define	ADIRECTION	"a=direction:active\r\n"#define	ADIRECTION_LEN	(sizeof(ADIRECTION) - 1)#define	AOLDMEDIP	"a=oldmediaip:"#define	AOLDMEDIP_LEN	(sizeof(AOLDMEDIP) - 1)#define	AOLDMEDIP6	"a=oldmediaip6:"#define	AOLDMEDIP6_LEN	(sizeof(AOLDMEDIP6) - 1)#define	AOLDMEDPRT	"a=oldmediaport:"#define	AOLDMEDPRT_LEN	(sizeof(AOLDMEDPRT) - 1)#define	ANORTPPROXY	"a=nortpproxy:yes\r\n"#define	ANORTPPROXY_LEN	(sizeof(ANORTPPROXY) - 1)

⌨️ 快捷键说明

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