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

📄 nathelper.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
	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) == -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	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)static intfix_nated_sdp_f(struct sip_msg* msg, char* str1, char* str2){	str body, body1, oldip, oldip1, newip;	int level, pf, pf1;	char *buf;	struct lump* anchor;	level = (int)(long)str1;	if (extract_body(msg, &body) == -1) {		LOG(L_ERR,"ERROR: fix_nated_sdp: cannot extract body from msg!\n");		return -1;	}	if (level & (ADD_ADIRECTION | ADD_ANORTPPROXY)) {		msg->msg_flags |= FL_FORCE_ACTIVE;		anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);		if (anchor == NULL) {			LOG(L_ERR, "ERROR: fix_nated_sdp: anchor_lump failed\n");			return -1;		}		if (level & ADD_ADIRECTION) {			buf = pkg_malloc(ADIRECTION_LEN * sizeof(char));			if (buf == NULL) {				LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n");				return -1;			}			memcpy(buf, ADIRECTION, ADIRECTION_LEN);			if (insert_new_lump_after(anchor, buf, ADIRECTION_LEN, 0) == NULL) {				LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n");				pkg_free(buf);				return -1;			}		}		if (level & ADD_ANORTPPROXY) {			buf = pkg_malloc(ANORTPPROXY_LEN * sizeof(char));			if (buf == NULL) {				LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n");				return -1;			}			memcpy(buf, ANORTPPROXY, ANORTPPROXY_LEN);			if (insert_new_lump_after(anchor, buf, ANORTPPROXY_LEN, 0) == NULL) {				LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n");				pkg_free(buf);				return -1;			}		}	}	if (level & FIX_MEDIP) {		if (extract_mediaip(&body, &oldip, &pf) == -1) {			LOG(L_ERR, "ERROR: fix_nated_sdp: can't extract media IP from the SDP\n");			goto finalize;		}		if (pf != AF_INET) {			LOG(L_ERR, "ERROR: fix_nated_sdp: "			    "not an IPv4 address in SDP\n");			goto finalize;		}		body1.s = oldip.s + oldip.len;		body1.len = body.s + body.len - body1.s;		if (extract_mediaip(&body1, &oldip1, &pf1) == -1) {			oldip1.len = 0;		}		if (oldip1.len > 0 && pf != pf1) {			LOG(L_ERR, "ERROR: fix_nated_sdp: mismatching "			    "address families in SDP\n");			return -1;		}		newip.s = ip_addr2a(&msg->rcv.src_ip);		newip.len = strlen(newip.s);		if (alter_mediaip(msg, &body, &oldip, pf, &newip, pf,		    1) == -1) {			LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP");			return -1;		}		if (oldip1.len > 0 && alter_mediaip(msg, &body, &oldip1, pf1,		    &newip, pf, 0) == -1) {			LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP");			return -1;		}	}finalize:	return 1;}static intextract_mediaip(str *body, str *mediaip, int *pf){	char *cp, *cp1;	int len, nextisip;	cp1 = NULL;	for (cp = body->s; (len = body->s + body->len - cp) > 0;) {		cp1 = ser_memmem(cp, "c=", len, 2);		if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')			break;		cp = cp1 + 2;	}	if (cp1 == NULL) {		LOG(L_DBG, "ERROR: extract_mediaip: no `c=' in SDP\n");		return -1;	}	mediaip->s = cp1 + 2;	mediaip->len = eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;	trim_len(mediaip->len, mediaip->s, *mediaip);	nextisip = 0;	for (cp = mediaip->s; cp < mediaip->s + mediaip->len;) {		len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;		if (nextisip == 1) {			mediaip->s = cp;			mediaip->len = len;			nextisip++;			break;		}		if (len == 3 && memcmp(cp, "IP", 2) == 0) {			switch (cp[2]) {			case '4':				nextisip = 1;				*pf = AF_INET;				break;			case '6':				nextisip = 1;				*pf = AF_INET6;				break;			default:				break;			}		}		cp = eat_space_end(cp + len, mediaip->s + mediaip->len);	}	if (nextisip != 2 || mediaip->len == 0) {		LOG(L_ERR, "ERROR: extract_mediaip: "		    "no `IP[4|6]' in `c=' field\n");		return -1;	}	return 1;}static intextract_mediaport(str *body, str *mediaport){	char *cp, *cp1;	int len;	cp1 = NULL;	for (cp = body->s; (len = body->s + body->len - cp) > 0;) {		cp1 = ser_memmem(cp, "m=", len, 2);		if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')			break;		cp = cp1 + 2;	}	if (cp1 == NULL) {		LOG(L_ERR, "ERROR: extract_mediaport: no `m=' in SDP\n");		return -1;	}	mediaport->s = cp1 + 2;	mediaport->len = eat_line(mediaport->s, body->s + body->len -	  mediaport->s) - mediaport->s;	trim_len(mediaport->len, mediaport->s, *mediaport);	if (mediaport->len > 6 && memcmp(mediaport->s, "audio", 5) == 0 &&	    isspace((int)mediaport->s[5])) {		mediaport->s += 5;		mediaport->len -= 5;	} else if (mediaport->len > 12 && memcmp(mediaport->s, "application", 11) == 0 &&	    isspace((int)mediaport->s[11])) {		mediaport->s += 11;		mediaport->len -= 11;	} else {		LOG(L_ERR, "ERROR: extract_mediaport: can't parse `m=' in SDP\n");		return -1;	}	cp = eat_space_end(mediaport->s, mediaport->s + mediaport->len);	mediaport->len = eat_token_end(cp, mediaport->s + mediaport->len) - cp;	mediaport->s = cp;	return 1;}static intalter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,  str *newip, int newpf, int preserve){	char *buf;	int offset;	struct lump* anchor;	str omip, nip, oip;	/* check that updating mediaip is really necessary */	if (oldpf == newpf && isnulladdr(oldip, oldpf))		return 0;	if (newip->len == oldip->len &&	    memcmp(newip->s, oldip->s, newip->len) == 0)		return 0;	/*	 * Since rewriting the same info twice will mess SDP up,	 * apply simple anti foot shooting measure - put flag on	 * messages that have been altered and check it when	 * another request comes.	 */#if 0	/* disabled: 	 *  - alter_mediaip is called twice if 2 c= lines are present	 *    in the sdp (and we want to allow it)	 *  - the message flags are propagated in the on_reply_route	 *  => if we set the flags for the request they will be seen for the	 *    reply too, but we don't want that	 *  --andrei	 */	if (msg->msg_flags & FL_SDP_IP_AFS) {		LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same "		  "SDP twice, check your config!\n");		return -1;	}#endif	if (preserve != 0) {		anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);		if (anchor == NULL) {			LOG(L_ERR, "ERROR: alter_mediaip: anchor_lump failed\n");			return -1;		}		if (oldpf == AF_INET6) {			omip.s = AOLDMEDIP6;			omip.len = AOLDMEDIP6_LEN;		} else {			omip.s = AOLDMEDIP;			omip.len = AOLDMEDIP_LEN;		}		buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);		if (buf == NULL) {			LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");			return -1;		}		memcpy(buf, omip.s, omip.len);		memcpy(buf + omip.len, oldip->s, oldip->len);		memcpy(buf + omip.len + oldip->len, CRLF, CRLF_LEN);		if (insert_new_lump_after(anchor, buf,		    omip.len + oldip->len + CRLF_LEN, 0) == NULL) {			LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n");			pkg_free(buf);			return -1;		}	}	if (oldpf == newpf) {		nip.len = newip->len;		nip.s = pkg_malloc(nip.len);		if (nip.s == NULL) {			LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");			return -1;		}		memcpy(nip.s, newip->s, newip->len);	} else {		nip.len = newip->len + 2;		nip.s = pkg_malloc(nip.len);		if (nip.s == NULL) {			LOG(L_ERR, "ERROR: alter_mediaip: out of memory\n");			return -1;		}		memcpy(nip.s + 2, newip->s, newip->len);		nip.s[0] = (newpf == AF_INET6) ? '6' : '4';		nip.s[1] = ' ';	}	oip = *oldip;	if (oldpf != newpf) {		do {			oip.s--;			oip.len++;		} while (*oip.s != '6' && *oip.s != '4');	}	offset = oip.s - msg->buf;	anchor = del_lump(msg, offset, oip.len, 0);	if (anchor == NULL) {		LOG(L_ERR, "ERROR: alter_mediaip: del_lump failed\n");		pkg_free(nip.s);		return -1;	}#if 0	msg->msg_flags |= FL_SDP_IP_AFS;#endif	if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {		LOG(L_ERR, "ERROR: alter_mediaip: insert_new_lump_after failed\n");		pkg_free(nip.s);		return -1;	}	return 0;}static intalter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,  int preserve){	char *buf;	int offset;	struct lump* anchor;	/* check that updating mediaport is really necessary */	if (newport->len == oldport->len &&	    memcmp(newport->s, oldport->s, newport->len) == 0)		return 0;	/*	 * Since rewriting the same info twice will mess SDP up,	 * apply simple anti foot shooting measure - put flag on	 * messages that have been altered and check it when	 * another request comes.	 */#if 0	/* disabled: - it propagates to the reply and we don't want this	 *  -- andrei */	if (msg->msg_flags & FL_SDP_PORT_AFS) {		LOG(L_ERR, "ERROR: alter_mediaip: you can't rewrite the same "		  "SDP twice, check your config!\n");		return -1;	}#endif	if (preserve != 0) {		anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);		if (anchor == NULL) {			LOG(L_ERR, "ERROR: alter_mediaport: anchor_lump failed\n");			return -1;		}		buf = pkg_malloc(AOLDMEDPRT_LEN + oldport->len + CRLF_LEN);		if (buf == NULL) {			LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n");			return -1;		}		memcpy(buf, AOLDMEDPRT, AOLDMEDPRT_LEN);		memcpy(buf + AOLDMEDPRT_LEN, oldport->s, oldport->len);		memcpy(buf + AOLDMEDPRT_LEN + oldport->len, CRLF, CRLF_LEN);		if (insert_new_lump_after(anchor, buf,		    AOLDMEDPRT_LEN + oldport->len + CRLF_LEN, 0) == NULL) {			LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n");			pkg_free(buf);			return -1;		}	}	buf = pkg_malloc(newport->len);	if (buf == NULL) {		LOG(L_ERR, "ERROR: alter_mediaport: out of memory\n");		return -1;	}	offset = oldport->s - msg->buf;	anchor = del_lump(msg, offset, oldport->len, 0);	if (anchor == NULL) {		LOG(L_ERR, "ERROR: alter_mediaport: del_lump failed\n");		pkg_free(buf);		return -1;	}	memcpy(buf, newport->s, newport->len);	if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {		LOG(L_ERR, "ERROR: alter_mediaport: insert_new_lump_after failed\n");		pkg_free(buf);		return -1;	}#if 0	msg->msg_flags |= FL_SDP_PORT_AFS;#endif	return 0;}static char *gencookie(){	static char cook[34];	sprintf(cook, "%d_%u ", (int)mypid, myseqn);	myseqn++;	return cook;}static intrtpp_test(int isdisabled, int force){	int rtpp_ver;	static int recheck_ticks = 0;	char *cp;	struct iovec v[2] = {{NULL, 0}, {"V", 1}};	if (force == 0) {		if (isdisabled == 0)			return 0;		if (recheck_ticks > get_ticks())			return 1;	}	cp = send_rtpp_command(v, 2);	if (cp == NULL) {		LOG(L_WARN,"WARNING: rtpp_test: can't get version of "		    "the RTP proxy\n");	} else {		rtpp_ver = atoi(cp);		if (rtpp_ver == SUP_CPROTOVER) {			LOG(L_INFO, "rtpp_test: RTP proxy found, support for "			    "it %senabled\n", force == 0 ? "re-" : "");			return 0;		}		LOG(L_WARN, "WARNING: rtpp_test: unsupported "		    "version of RTP proxy found: %d supported, "		    "%d present\n", SUP_CPROTOVER, rtpp_ver);	}	LOG(L_WARN, "WARNING: rtpp_test: support for RTP proxy "	    "has been disabled%s\n",	    rtpproxy_disable_tout < 0 ? "" : " temporarily");	if (rtpproxy_disable_tout >= 0)		recheck_ticks = get_ticks() + rtpproxy_disable_tout;	return 1;}static char *send_rtpp_command(struct iovec *v, int vcnt){	struct sockaddr_un addr;	int fd, len, i;	char *cp;	static char buf[256];	struct pollfd fds[1];	len = 0;	cp = buf;	if (umode == 0) {		memset(&addr, 0, sizeof(addr));		addr.sun_family = AF_LOCAL;		strncpy(addr.sun_path, rtpproxy_sock,		    sizeof(addr.sun_path) - 1);#ifdef HAVE_SOCKADDR_SA_LEN		addr.sun_len = strlen(addr.sun_path);#endif

⌨️ 快捷键说明

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