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/