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/