[Serusers] NATHelper IPv4-IPv6

Ahmed Kellal ahmedkellal at hotmail.com
Wed Aug 31 14:13:15 CEST 2005


Hello everyone,

I am working on setting up a heterogeneous platform with both IPv4 and IPv6 
UAs. Problem I am facing right now is that I need to add a little to the 
code, in order to:

1- Extract the hostname part of the Contact header field, when needed
2- Change the said hostname contact
3- Extract the IP (v4 or v6) address in the owner ("o=") field of the SDP 
body
4- Change it with the value the RTP Proxy assigns dynamically to represent 
an IPv4 UA in the IPv6 world and vice versa

In order to do these things, I tried to understand as much as I can of the 
code of the NAtHelper module. I wrote four functions to do the above, but 
(naturally enough in my case :-)) they're not doing what I want them to. So 
if anyone could help me out here, I would sure be grateful, esp. that I have 
a serious deadline! Thanks

Here are the sections I added (I drew inspiration from the functions already 
existing in nathelper.c)

/************* Added Section 1: Define the newly inserted functions 
****************/

static int extract_sip_contact_host(struct sip_msg *, char *);
static int extract_sdp_ownerip(str *, str *, int *);
static int alter_sdp_ownerip(struct sip_msg *, str *, str *, int, str *, 
int, int);
static int modify_contact (struct sip_msg *, char *, char *, char *);

/************* End of Added Section 1 ******************************/

/********************* Added Section 2: The modify_contact function 
******************/
/********* Replaces ip:port pair in the Contact: field with the hostname 
desired **********/

static int modify_contact (struct sip_msg* msg, char* str1, char* str2, 
char* hostname)
{
	int offset, len, len1;
	char *cp, *buf, temp[2];
	contact_t* c;
	struct lump* anchor;
	struct sip_uri uri;

	if (get_contact_uri(msg, &uri, &c) == -1)
		return -1;
	if (uri.proto != PROTO_UDP && uri.proto != PROTO_NONE)
		return -1;
	if (uri.port.len == 0)
		uri.port.s = uri.host.s + uri.host.len;

	offset = c->uri.s - msg->buf;
	anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT);
	if (anchor == 0)
		return -1;

	cp = hostname;
	len = c->uri.len + strlen(cp) + 6 /* :port */ - (uri.port.s + uri.port.len 
- uri.host.s) + 1;
	buf = pkg_malloc(len);
	if (buf == NULL) {
		LOG(L_ERR, "ERROR: fix_contact: out of memory\n");
		return -1;
	}
	temp[0] = uri.host.s[0];
	temp[1] = c->uri.s[c->uri.len];
	c->uri.s[c->uri.len] = uri.host.s[0] = '\0';
	len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp, msg->rcv.src_port,
	    uri.port.s + uri.port.len);
	if (len1 < len)
		len = len1;
	uri.host.s[0] = temp[0];
	c->uri.s[c->uri.len] = temp[1];
	if (insert_new_lump_after(anchor, buf, len, HDR_CONTACT) == 0) {
		pkg_free(buf);
		return -1;
	}
	c->uri.s = buf;
	c->uri.len = len;

	return 1;
}

/****************************** End of Added Section 2 
************************/

/**** Added Section 3: Function to extract the host part only of the Contact 
SIP URI *******/

static int extract_sip_contact_host(struct sip_msg* msg, char* hostname)
{
	struct sip_uri uri;
	contact_t* c;
	if (get_contact_uri(msg,&uri,&c)==-1)
		return -1;
	*hostname = uri.host.s;
	return 1;
}

/*********************** End of Added Section 3 
******************************/

/************ Added Section 4: Function to extract the IP @ in 'o' SDP 
parameter **********/

static int extract_sdp_ownerip(str *body, str *ownerip, 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, "o=", len, 2);
		if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
			break;
		cp = cp1 + 2;
	}

	if (cp1 == NULL) {
		LOG(L_DBG, "ERROR: extract_mediaownerip: no `o=' in SDP\n");
		return -1;
	}
	ownerip->s = cp1 + 2;
	ownerip->len = eat_line(ownerip->s, body->s + body->len - ownerip->s) - 
ownerip->s;
	trim_len(ownerip->len, ownerip->s, *ownerip);

	nextisip = 0;
	for (cp = ownerip->s; cp < ownerip->s + ownerip->len;) {
		len = eat_token_end(cp, ownerip->s + ownerip->len) - cp;
		if (nextisip == 1) {
			ownerip->s = cp;
			ownerip->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, ownerip->s + ownerip->len);
	}
	if (nextisip != 2 || ownerip->len == 0) {
		LOG(L_ERR, "ERROR: extract_mediaownerip: "
		    "no `IP[4|6]' in `c=' field\n");
		return -1;
	}
	return 1;
}

/************************** End of Added Section 4 
****************************/

/**** Added Section 5: Function to alter the IP information in the 'o' SDP 
parameter ********/

static int alter_sdp_ownerip(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;

	if (preserve != 0) {
		anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
		if (anchor == NULL) {
			LOG(L_ERR, "ERROR: alter_sdp_ownerip: 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_sdp_ownerip: 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_sdp_ownerip: 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_sdp_ownerip: 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_sdp_ownerip: 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_sdp_ownerip: del_lump failed\n");
		pkg_free(nip.s);
		return -1;
	}
	if (insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
		LOG(L_ERR, "ERROR: alter_sdp_ownerip: insert_new_lump_after failed\n");
		pkg_free(nip.s);
		return -1;
	}
	return 0;
}

/***************** End of Added Section 5 ******************************/

/***********Added Section 6: added section in 
force_rtpproxy_2****************/

	if (extract_sdp_ownerip(&body, &oldownerip, &ownerpf) == -1) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2_2: can't extract media owner IP "
		    "from the message\n");
		return -1;
	}
	if (asymmetric != 0 || real != 0) {
		newownerip = oldownerip;
	} else {
		newownerip.s = ip_addr2a(&msg->rcv.src_ip);
		newownerip.len = strlen(newownerip.s);
	}
	body2.s = oldownerip.s + oldownerip.len;
	body2.len = body.s + body.len - body2.s;
	if (extract_sdp_ownerip(&body2, &oldownerip1, &ownerpf1) == -1) {
		oldownerip1.len = 0;
	}
	if (oldownerip1.len > 0 && ownerpf != ownerpf1) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2_2: mismatching address "
		    "families in SDP\n");
		return -1;
	}


/********************* End of Added Section 6********************/


/*********** Added Section 7: added section in 
force_rtpproxy_2****************/

	if (alter_sdp_ownerip(msg, &body, &oldownerip, ownerpf, &newip, pf1, 0) == 
-1)
		return -1;
	if (oldownerip1.len > 0 &&
	    alter_sdp_ownerip(msg, &body2, &oldownerip1, ownerpf, &newip, pf1, 0) 
== -1)
		return -1;

/*********** End of Added Section 7************/

I apologize for this email's length, but I'm trying to be as detailed as I 
can, and I really do need the help :-)

Thank you again

Ahmed

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE! 
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/




More information about the sr-users mailing list