[Devel] Extended nathelper

Walter Schober walter.schober at neotel.at
Tue Feb 28 08:48:38 CET 2006


Skipped content of type multipart/alternative-------------- next part --------------
Nathelper Patch for registering on remote proxies
-------------------------------------------------

V 0.2 
20060212
WSC walter.schober at neotel.at

-------------------------------------------------

Description: Openser is placed in front of another proxy not supporting RFC 3327 (Patch Header Support).
Using module nathelper the OpenSER detects nated clients and modifies the Contact field of the register. 
The Contact header is expanded by a new "route", which is substituted instead of the IP:Port the 
register is received from. 
The operation is done after fixing the Contact in
	fix_nated_contact();
Original fix_nated_contact() just replaces the host:port with host:port from where the request was 
received from.
If the module parameter "contact_expander" is set, this value is inserted behind the user@ replacing the 
fixed original host port.
e.g. original Contact is
	Contact: <sip:user at 192.168.1.1:5555;some-uri-param>;additional-params

the fix_nated_contact() replaces that with the IP from where the request was received from:
	Contact: <sip:user at some_ip:port;some-uri-param>;additional-params

If contact_expander is set, this string is inserted as
	Contact: <sip:user at value-of-contact-expander;x-orig=some_ip:port;x-orig-nat=original-contact;some-uri-param>;additional-params

e.g. contact_exander = 1.2.3.4:5066, resulting in
	Contact: <sip:user at 1.2.3.4:5066;x-orig=33.44.55.66:5066;x-orig-nat=192.168.1.1:5062;some-uri-param>;additional-params
	
A Invite to such a contact results in 
	INVITE sip:user at 1.2.3.4:5066;x-orig=33.44.55.66:5066;x-orig-nat=192.168.1.1:5062;some-uri-param

which could be replaced by e.g. textops and avp_ops
        avp_write("$ruri","$x-orig");
        if (subst_uri('/^sip:(.+)@.*;x-orig-nat=(.*)$/sip:\1@\2/i')) {
                avp_subst("$x-orig","/^(.*)@.*;x-orig=(.*);x-orig-nat=.*$/\1@\2/");
                avp_pushto("$duri","$x-orig");
		route(1);

forwarding to the original contact address, but to NATed contact address.


New Module Param:
--------------------------------------------------
modparam("nathelper", "contact_expander", "1.2.3.4:5066")


New Function Call:
--------------------------------------------------
None.


Example:
--------------------------------------------------
# add myself as an alias
alias=1.2.3.4:5066

# set contact_expander to myself
modparam("nathelper", "contact_expander", "1.2.3.4:5066")

# avpops
modparam("avpops", "avp_aliases", "x-orig=i:32")

# is request is directed to me
if (uri==myself) {
	# check, if we have to restore old destination
        avp_write("$ruri","$x-orig");
        if (subst_uri('/^sip:(.+)@.*;x-orig-nat=(.*)$/sip:\1@\2/i')) {
                avp_subst("$x-orig","/^(.*)@.*;x-orig=(.*);x-orig-nat=.*$/\1@\2/");
                avp_pushto("$duri","$x-orig");
		# forwared to destination
		route(1);
		return;
	}
}

# ... do something ...

# fix the Register as usual
if (method=="REGISTER" || method=="INVITE" || method=="REFER") {
	if (nat_uac_test("18")) {
		fix_nated_contact();
		force_rport();
		append_hf("P-hint: nathelper applied\r\n");
	} else {
		append_hf("P-hint: nathelper not applied\r\n");
	};
};

# ... continue ... do something with the request


Installation
----------------------------------------------------
Patch the nathelper.c located in modules/nathelper executing
	cp nathelper.c nathelper.c.orig
	patch nathelper.c <nathelper.patch
	
Rebuild module nathelper
	make modules=modules/nathelper modules
	make install

The patch is based on OpenSER 1.0.0.

Changes are in function fix_nated_contact_f() only + parameter definitions.
	
Restart OpenSER.


-----------------------------------------------------


New function fix_nated_contact_f():

static int
fix_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;

        if (contact_expander.len) {
                LOG(L_DBG, "Expanding Contact: %s\n", contact_expander.s);
                len += contact_expander.len + hostport.len + 20;
        }
        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';

        if (contact_expander.len) {
                // sip:user:password at host:port ->
                // sip:user:password at HOST:PORT;x-orig=host:port;x-orig-nat=priv-host:priv-port
                len1 = snprintf(buf, len, "%s%s;x-orig=%s:%d;x-orig-nat=%c%s", c->uri.s,
                        contact_expander.s,
                        cp, msg->rcv.src_port,
                        temp[0],
                        hostport.s + 1);
        } else {
                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;
}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: nathelper.patch
Type: application/octet-stream
Size: 2229 bytes
Desc: not available
Url : http://openser.org/pipermail/devel/attachments/20060228/ab2ff2e3/nathelper.obj


More information about the Devel mailing list