# &adminguide;

## Overview

This module offers topology hiding for INVITE-based dialogs, by stripping the SIP routing headers that show topology details . The script interpreter gets the SIP messages with full content, so all existing functionality is preserved.

The module is transparent for the configuration writer. It only needs to be loaded (tune the module parameters if needed).

It also works for SIP MESSAGE or other requests that do not create a dialog (e.g., OPTIONS) -- record_route() must be used for them as well, the headers are not going to be in the messages sent to the network, they are needed to know local addresses used to communicate with each side. This module is designed to work for presence (SUBSCRIBE-based) dialogs too.

The REGISTER and PUBLISH requests are skipped from processing by this module, expected to be terminated on a local SIP server.

## Dependencies

### &kamailio; Modules

The following modules must be loaded before this module:

- rr module - server must perform record routing to ensure in-dialog requests are encoded/decoded (it must be done for all initial requests).

- database module - to store the data for topology stripping and restoring.

- topoh module - in case of Call-ID mask for Call-ID masking.

### External Libraries or Applications

The following libraries or applications must be installed before running &kamailio; with this module loaded:

- none.

## Parameters

### `storage` (str)

Type of storage, valid types are:

- db - Database Backend

- redis - Redis Backend

- htable - htable module Backend

Default value is db.

#### Set `storage` parameter

    ...
    modparam("topos", "storage", "redis")
    ...

### `db_url` (str)

Database URL.

Default value is &defaultdb;.

#### Set `db_url` parameter

    ...
    modparam("topos", "db_url", "&exampledb;")
    ...

### `mask_callid` (int)

Whether to encode the Call-id: header. Some SIP extensions include the Call-id in the SIP message payload or header, so it is safe to not encode Call-id in such cases. Well-known extensions such as call transfer or conference join will be added to work with encoded Call-id. Topoh module should be loaded with use_mode parameter set to 1

Default value is 0 (do not mask).

#### Set `mask_callid` parameter

    ...
    modparam("topos", "mask_callid", 1)
    ...

### `sanity_checks` (int)

If set to 1, topos module will bind to sanity module in order to perform sanity checks over received SIP request. Default sanity checks are done. It is useful to check if received request is well formatted before proceeding to encoding/decoding.

Default value is 0 (do not bind to sanity module).

#### Set `sanity_checks` parameter

    ...
    modparam("topos", "sanity_checks", 1)
    ...

### `branch_expire` (int)

Interval in seconds after which the branch records are deleted.

Default value is 180 (3 min).

#### Set `branch_expire` parameter

    ...
    modparam("topos", "branch_expire", 300)
    ...

### `dialog_expire` (int)

Interval in seconds after which the dialog records are deleted. Keep in mind that the module does not update the dialog timestamp after the initial call setup on re-INVITEs or other in-dialog messages. So set a large enough value (according your longest call duration) to prevent problems in re-writing messages. This key is only relevant for INVITE dialog. SUBSCRIBE dialog records lifetime are based on value set in expires header. Moreover each re-SUBSCRIBEs update the dialog timestamp.

Default value is 10800 (3 hours).

#### Set `dialog_expire` parameter

    ...
    modparam("topos", "dialog_expire", 3600)
    ...

### `clean_interval` (int)

Interval in seconds to run the clean up of stored records.

Default value is 60 (1 min).

#### Set `clean_interval` parameter

    ...
    modparam("topos", "clean_interval", 30)
    ...

### `event_callback` (str)

The name of the function in the KEMI configuration file (embedded scripting language such as Lua, Python, ...) to be executed instead of event_route[...] blocks.

The function receives a string parameter with the name of the event.

Default value is 'empty' (no function is executed for events).

#### Set `event_callback` parameter

    ...
    modparam("topos", "event_callback", "ksr_topos_event")
    ...
    -- event callback function implemented in Lua
    function ksr_topos_event(evname)
    	KSR.info("===== topos module triggered event: " .. evname .. "\n");
    	return 1;
    end
    ...

### `event_mode` (int)

Control what event_route blocks to be executed. It is a bitmask of:

- 1 - execute event_route[topos:msg-outgoing]

- 2 - execute event_route[topos:msg-sending]

- 4 - execute event_route[topos:msg-incoming]

- 8 - execute event_route[topos:msg-receiving]

Default value is 15 (execute all event_route blocks).

#### Set `event_mode` parameter

    ...
    modparam("topos", "event_mode", 2)
    ...

### `contact_host` (str)

You may need to control the host part of the Contact header added by topos. If the xavu_field_contact_host parameter is set, this value is ignored. For example when using TLS with TOPOS the remote UAS must be able to open a new TLS socket to the contact header. In this case, the contact header must contain a domain name with a trusted CA signed certitificate.

Default value is taken from the Record-Route URI.

#### Set `contact_host` parameter

    ...
    modparam("topos", "contact_host", "proxy.domain.com")
    ...

### `contact_mode` (int)

Control the mode where the key to lookup the message data from the database or redis server is stored. The default is to use the Contact user (0), alternatively a Contact URI parameter can be used (1) with values from the SIP message, or from AVP variables (2). Contact mode (3) is similar to mode 2, but for the case when we want to alter the domain part. This can be useful for interoperating which gateways that need a certain user part in the Contact URI.

In mode (1) the a-side contact user is taken from the request URI and the b-side contact user from the Contact header of the processed initial SIP request.

If you use the mode (2), you need to configure the xavu_field_a_contact and xavu_field_b_contact parameter. Furthermore you need to assign values to them during the processing of the initial SIP request.

If you use the mode (3), you need to configure the xavu_field_a_contact_host and xavu_field_b_contact_host parameter. Furthermore you need to assign values to them during the processing of the initial SIP request.

The name of the Contact URI parameter can be customized with the cparam_name parameter.

Default value is 0 - use the Contact user

#### Set `contact_mode` parameter

    ...
    modparam("topos", "contact_mode", 1)
    ...

### `cparam_name` (int)

Name of the Contact URI parameter to store the database or redis server key for message lookup.

This parameter is only used when the contact_mode parameter is set to 1 or 2.

Default value is tps.

#### Set `cparam_name` parameter

    ...
    modparam("topos", "cparam_name", "xyz")
    ...

### `xavu_cfg` (str)

Name of root XAVU to hold config-specific values to be used by module at runtime.

Note: this parameter must be set if any other parameter prefixed with `xavu_field_` is used.

Default value is NULL (disabled).

#### Set `xavu_cfg` parameter

    ...
    modparam("topos", "xavu_cfg", "_tps_")
    modparam("topos", "xavu_field_a_contact", "a_contact")
    ...
        $xavu(_tps_=>a_contact) = "...";
    ...

### `xavu_field_a_contact` (str)

Name of the field inside root XAVU specified by `xavu_cfg` to evaluate for the A-side Contact Header user part. This parameter is only necessary in contact_mode (2).

Default value is NULL (disabled).

#### Set `xavu_field_a_contact` parameter

    ...
    modparam("topos", "xavu_cfg", "_tps_")
    modparam("topos", "xavu_field_a_contact", "a_contact")
    ...
        $xavu(_tps_=>a_contact) = "...";
    ...

### `xavu_field_b_contact` (str)

Name of the field inside root XAVU specified by `xavu_cfg` to evaluate for the B-side Contact Header user part. This parameter is only necessary in contact_mode (2).

Default value is NULL (disabled).

#### Set `xavu_field_b_contact` parameter

    ...
    modparam("topos", "xavu_cfg", "_tps_")
    modparam("topos", "xavu_field_b_contact", "b_contact")
    ...
        $xavu(_tps_=>b_contact) = "...";

    ...

### `xavu_field_contact_host` (str)

Control from where to take the host part of the Contact header added by topos. This parameter allows to take the value from an XAVU during run-time, it specifies the field inside XAVU "xavu_cfg". If this parameter is set, the contact_host parameter is ignored. For example when using TLS with TOPOS the remote UAS must be able to open a new TLS socket to the contact header. In this case, the contact header must contain a domain name with a trusted CA signed certitificate.

Default value is empty, not set.

#### Set `xavu_field_contact_host` parameter

    ...
    modparam("topos", "xavu_cfg", "_tps_")
    modparam("topos", "xavu_field_contact_host", "contact_host")
    ...
        $xavu(_tps_=>contact_host) = "kamailio.org";
    ...

### `rr_update` (int)

If set to 1, topos module will track and update record route changes on re-invite.

Default value is 0 (do not update record route changes within dialog).

#### Set `rr_update` parameter

    ...
    modparam("topos", "rr_update", 1)
    ...

### `context` (str)

Set the global context for topos instance.

The value has to be maximum 12 characters.

Default value is NULL (disabled).

#### Set `context` parameter

    ...
    modparam("topos", "context", "srvone")
    ...

### `methods_nocontact` (str)

List of SIP methods to skip adding Contact header for.

Default value is BYE,CANCEL,PRACK.

#### Set `methods_nocontact` parameter

    ...
    modparam("topos", "methods_nocontact", "CANCEL,PRACK")
    ...

### `header_mode` (int)

List of headers to disable multiple comma separated values inserted in compact form. Altough compact form is RFC compliant this parameter gives possibilty to disable compact form header values for UA that don't support or can't handle it. The following options are available: (1) - disable multiple comma separated values for Via header (2) - disable multiple comma separated values for Record-Route header (4) - disable multiple comma separated values for Route header

Default value is 0.

#### Set `header_mode` parameter

    ...
    modparam("topos", "header_mode", 1)
    ...

### `methods_noinitial` (str)

List of SIP methods to skip doing topos if it is an initial request (no To-tag).

Default value is (no method).

#### Set `methods_noinitial` parameter

    ...
    modparam("topos", "methods_noinitial", "OPTIONS,NOTIFY")
    ...

### `version_table` (integer)

If set to 0, the module will skip checking the version of the tables.

Default value is 1 (check for table version).

#### `version_table` parameter usage

    ...
    modparam("topos", "version_table", 0)
    ...

### `methods_update_time` (str)

List of SIP methods (comma separated) for which the dialog timestamp (rectime) should be updated in the topos_d table when processing in-dialog requests. This allows extending the dialog lifetime for specific methods beyond the initial INVITE.

Default value is SUBSCRIBE.

#### Set `methods_update_time` parameter

    ...
    modparam("topos", "methods_update_time", "SUBSCRIBE,UPDATE,INVITE")
    ...

## Functions

### `tps_set_context(ctx)`

Update the context at runtime. If the value is empty string, then the runtime context is reset.

This function can be used from ANY_ROUTE.

#### `tps_set_context` usage

    ...
    request_route {
        ...
        tps_set_context("srvone");
        ...
    }
    ...

## Event Routes

### event_route[topos:msg-outgoing]

It is executed before doing topology stripping processing for an outgoing SIP message. If 'drop' is executed inside the event route, then the module skips doing the outbound part of topology stripping.

The event route is executed with an internal fake SIP message for the purpose of performace (i.e., no parsing of the outgoing message is done), therefore the R-URI, headers and body do not reflect the content of the outgoing message. However, inside the event route the variables $sndto(ip), $sndto(port) and $sndto(proto) point to the real destination of the SIP message.

#### Usage of event_route[topos:msg-outgoing]

    ...
    event_route[topos:msg-outgoing] {
      if($sndto(ip)=="10.1.1.10") {
        drop;
      }
    }
    ...

### event_route[topos:msg-sending]

It is executed before doing topology stripping processing for a SIP message to be sent out, being executed after event_route[topos:msg-outgoing]. If 'drop' is executed inside the event route, then the module skips doing the outbound part of topology stripping.

A copy of the SIP message to be sent out is made available in this event route, thefore the R-URI, headers and body reflect the content of the outgoing SIP message. Inside the event route the variables $sndto(ip), $sndto(port) and $sndto(proto) point to the real destination of the SIP message.

#### Usage of event_route[topos:msg-sending]

    ...
    event_route[topos:msg-sending] {
      if(is_request() and $fU=="alice") {
        drop;
      }
    }
    ...

### event_route[topos:msg-incoming]

It is executed before doing topology stripping processing for an incoming SIP message. If 'drop' is executed inside this event route, then the module skips doing the inbound part of topology stripping.

The event route is executed with an internal fake SIP message for the purpose of performace (i.e., no parsing of the incoming message is done), therefore the R-URI, headers and body do not reflect the content of the incoming message. However, inside the event route the variables $si, $sp and $proto point to the real source address of the SIP message, as well as the keywords src_port and dst_port.

#### Usage of event_route[topos:msg-incoming]

    ...
    event_route[topos:msg-incoming] {
      if($si=="10.1.1.10") {
        drop;
      }
    }
    ...

### event_route[topos:msg-receiving]

It is executed before doing topology stripping processing for a SIP message that was received, being executed after event_route[topos:msg-incoing]. If 'drop' is executed inside this event route, then the module skips doing the inbound part of topology hiding.

A copy of the incoming SIP message is made available in this event route, thefore the R-URI, headers and body reflect the content of the incoming SIP message. Inside the event route the variables $si, $sp and $proto point to the real source address of the SIP message, as well as the keywords src_port and dst_port.

#### Usage of event_route[topos:msg-receiving]

    ...
    event_route[topos:msg-receiving] {
      if(is_request() and $fU=="alice") {
        drop;
      }

      if($sp==5555 || $si=="1.2.3.4") {
        drop;
      }

      if(src_port==1234 || dst_port==5678) {
        drop;
      }
    }
    ...