<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<section id="permissions.functions" xmlns:xi="http://www.w3.org/2001/XInclude">
    <sectioninfo>
    </sectioninfo>

    <title>Functions</title>

    <section id="allow_routing0">
	<title>
	    <function>allow_routing()</function>
	</title>
	<para>
	    Returns true if all pairs constructed as described in <xref
		linkend="call_routing"/> have appropriate permissions
		according to the configuration files. This function uses
		default configuration files specified in
		<varname>default_allow_file</varname> and
		<varname>default_deny_file</varname>.
	</para>
	<example>
	    <title><function>allow_routing</function> usage</title>
	    <programlisting>
...
if (allow_routing()) {
    t_relay();
};
...
	    </programlisting>
	</example>
    </section>

    <section id="allow_routing1">
	<title>
	    <function>allow_routing(basename)</function>
	</title>
	<para>
	    Returns true if all pairs constructed as described in <xref
		linkend="call_routing"/> have appropriate permissions according
		to the configuration files given as parameters.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para>
		    <emphasis>basename</emphasis> - Basename from which allow
		    and deny filenames will be created by appending contents of
		    <varname>allow_suffix</varname> and
		    <varname>deny_suffix</varname> parameters.
		</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
		</listitem>
	    </itemizedlist>
	    <example>
		<title><function>allow_routing(basename)</function> usage</title>
		<programlisting>
...
if (allow_routing("basename")) {
    t_relay();
};
...
	    </programlisting>
	</example>
    </section>

    <section id="allow_routing">
	<title>
	    <function>allow_routing(allow_file, deny_file)</function>
	</title>
	<para>
	    Returns true if all pairs constructed as described in <xref
		linkend="call_routing"/> have appropriate permissions according
		to the configuration files given as parameters.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>allow_file</emphasis> - File containing allow rules.</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	    <listitem>
		<para><emphasis>deny_file</emphasis> - File containing deny rules.</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	</itemizedlist>
	<example>
	    <title><function>allow_routing(allow_file, deny_file)</function> usage</title>
	    <programlisting>
...
if (allow_routing("rules.allow", "rules.deny")) {
    t_relay();
};
...
	    </programlisting>
	</example>
    </section>

    <section id="allow_register">
	<title>
	    <function>allow_register(basename)</function>
	</title>
	<para>
	    The function returns true if all pairs constructed as described in
	    <xref linkend="registration_permissions"/> have appropriate
	    permissions according to the configuration files given as
	    parameters.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>basename</emphasis> - Basename from which allow
		    and deny filenames will be created by appending contents of
		    <varname>allow_suffix</varname> and
		    <varname>deny_suffix</varname> parameters.
		</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	</itemizedlist>
	<example>
	    <title><function>allow_register(basename)</function> usage</title>
	    <programlisting>
...
if (method=="REGISTER") {
    if (allow_register("register")) {
        save("location");
        break;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};
...
	    </programlisting>
	</example>
    </section>

    <section id="allow_register2">
	<title>
	    <function>allow_register(allow_file, deny_file)</function>
	</title>
	<para>
	    The function returns true if all pairs constructed as described in
	    <xref linkend="registration_permissions"/> have appropriate
	    permissions according to the configuration files given as
	    parameters.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>allow_file</emphasis> - File containing allow rules.</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	    <listitem>
		<para><emphasis>deny_file</emphasis> - File containing deny rules.</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	</itemizedlist>
	<example>
	    <title><function>allow_register(allow_file, deny_file)</function> usage</title>
	    <programlisting>
...
if (method=="REGISTER") {
    if (allow_register("register.allow", "register.deny")) {
        save("location");
        break;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};
...
</programlisting>
	</example>
    </section>
    
    <section id="allow_refer_to">
	<title>
	    <function>allow_refer_to(basename)</function>
	</title>
	<para>
		The function returns true if all pairs constructed as
		described in <xref linkend="registration_permissions"/> have appropriate permissions
		according to the configuration files given as parameters.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>basename</emphasis> - Basename from which allow
		    and deny filenames will be created by appending contents of
		    <varname>allow_suffix</varname> and
		    <varname>deny_suffix</varname> parameters.
		</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	</itemizedlist>
	<example>
	    <title><function>allow_register(basename)</function> usage</title>
	    <programlisting>
...
if (method=="REGISTER") {
    if (allow_register("register")) {
        save("location");
        break;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};
...
	    </programlisting>
	</example>
    </section>

    <section id="allow_refer_to(allow_file, deny_file)">
	<title>
	    <function>allow_refer_to(allow_file, deny_file)</function>
	</title>
	<para>
		The function returns true if all pairs constructed as
		described in Section 1.1.2 have appropriate permissions
		according to the configuration files given as parameters.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>allow_file</emphasis> -  File containing allow rules.
		</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	    <listitem>
		<para><emphasis>deny_file</emphasis> -  File containing deny rules.
		</para>
		<para>
		    If the parameter doesn't contain full pathname then the
		    function expects the file to be located in the same
		    directory as the main configuration file of the server.
		</para>
	    </listitem>
	</itemizedlist>
	<example>
	    <title><function>allow_register(allow_file, deny_file)</function> usage</title>
	    <programlisting>
...
if (method=="REFER") {
    if (allow_register("refer.allow", "refer.deny")) {
       ...
    } else {
        sl_send_reply("403", "Forbidden");
    };
};
...
	    </programlisting>
	</example>
    </section>

    <section id="ipmatch (string/AVP/select, [avp])">
	<title>
	    <function>ipmatch (string/AVP/select, [avp])</function>
	</title>
	<para>
		The function tries to find an IP address and port pair
		(defined by the first function parameter) in the cached
		database table. Port is optional, it is compared only if
		both the function parameter and the database entry contain it. 
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>string/AVP/select</emphasis> -  File containing allow rules.
		</para>
		<itemizedlist>
			<listitem>
				<para><emphasis>string</emphasis>:</para>
				<para>
				"src": the source address of the packet is used
		        "via2": the ip address of the 2nd via line is used
		        other values are not defined currently
				</para>
			</listitem>
			<listitem>
				<para><emphasis>AVP</emphasis>:</para>				
				<para>
					e.g. "$myavp"
				</para>
			</listitem>
			<listitem>
				<para><emphasis>select call</emphasis>:</para>				
				<para>
					e.g. "@via[0].host"
				</para>
			</listitem>
		</itemizedlist>
	    </listitem>
	    <listitem>
		<para>
			The second parameter is optional, it is used to set an AVP
			value from the database. Suitable for assigning logical
			identifiers to gateways.
		</para>
	    </listitem>
	</itemizedlist>
	<para>
		Note that IPv6 addresses must be enclosed in square brackets
		in case of port is defined: [1111:2222::3333]:5060
	</para>
    </section>

    <section id="ipmatch_onsend(string)">
	<title>
	    <function>ipmatch_onsend (string)</function>
	</title>
	<para>
		<function>ipmatch()</function> function replacement for <emphasis>onsend_route</emphasis> block.
	</para>
	<para>
		The function accepts only string parameter, because even AVP
		reading is unsafe in onsend_route.
	</para>
		  
	<para>Meaning of the parameter:</para>
	<itemizedlist>
	    <listitem>
		<para><emphasis>"dst"</emphasis>:		
		</para>
		<para>
		the destination address is used
		</para>
	    </listitem>
	    <listitem>
		<para><emphasis>"ruri"</emphasis>:		
		</para>
		<para>
		the ip:port pair is extracted from the Request URI
		</para>
	    </listitem>
	</itemizedlist>
	<para>
		The function can be used for example to catch unauthorized requests
		going to gateways: Use a flag to mark the call as PSTN either
		in request or in failure_route, and do not touch it in onreply_route.
		See the examples below.
	</para>
    </section>

    <section id="ipmatch_filter (unsigned int)">
	<title>
	    <function>ipmatch_filter (unsigned int)</function>
	</title>
	<para>
		Entries in the database can be marked to group the different kind
		of network elements. The function sets the filter which is used on
		the mark while comparing the IP addresses. The mark must be the
		power of 2 in the database!
	</para>
	<para>
		Note that ipmatch() and ipmatch_onsend() functions reset the filter!
	</para>
		  
	<example>
	    <title><function>ipmatch_filter (unsigned int)</function> usage</title>
	    <programlisting>
+-----------------+-------------------+------+------+
| ip              | avp_val           | mark | flag |
+-----------------+-------------------+------+------+
| 1111:2222::1001 | first_gw          |    1 |    1 |
| 10.38.2.10:5060 | second_gw         |    1 |    1 |
| 10.0.0.10       | first_peering     |    2 |    1 |
+-----------------+-------------------+------+------+


route[0] {
  # is this a request from a GW?
  ipmatch_filter("1");
  if (ipmatch("src", "$gw_id")) {
    # yes, it is from a GW
    ...
  } else {
    # is this a request from a peering partner?
    ipmatch_filter("2");
    if (ipmatch("src", "$peering_id")) {
       # yes, it is from a peering partner
       ...
    };
  }
  ...
  # request goes to PSTN
  setflag(PSTN);
}

onsend_route[0] {
  if (method == "INVITE" &amp;&amp; (!isflagset(PSTN))) {
     # is this a request to a GW?
     ipmatch_filter("1");
     if (ipmatch_onsend("dst")) {
        # request is not marked with PSTN flag, but it goes to a gateway
        drop;
     }
  }
  ...
}
	    </programlisting>
	</example>
    </section>

	<section id="ip_is_trusted">
	<title>
	    <function>ip_is_trusted(ip_set, ip)</function>
	</title>
	<para>
		The function returns true if <emphasis>ip</emphasis> is contained
		in <emphasis>ip_set</emphasis>. Both IPv4 and IPv6 are supported.
	</para>
	<para>Meaning of the parameters is as follows:</para>
	<itemizedlist>
	    <listitem>
		<para>
			<emphasis>ip_set</emphasis> is identified by comma/space/semicolon
			delimited list of IP addresses or subnet masks. The subnet mask
			is written in IP_slash_number form or as IP. If the mask is not mentioned 
			then default value is taken, the default value is number of bits
			of particular IP address, i.e. 32 in case of IPv4, 128 in case of IPv6.
		</para>
		<para>
			Besides list also ip set identifier declared by <varname>declare_ipset</varname> may
			be provided. In this case ip is checked against set maintainded by RPC commands.
		</para>
	    </listitem>
		<listitem>
		<para>
			<emphasis>ip</emphasis> to test. Besides direct address in string form there
			are extra identifiers to force IP related to current message:
			<emphasis>Source</emphasis>, <emphasis>Destination</emphasis>, <emphasis>Received</emphasis>.
			Note that only the first character is essential.
		</para>
		</listitem>
	</itemizedlist>
	<example>
	    <title><function>ip_is_trusted</function> usage</title>
	    <programlisting>
modparam("permissions", "declare_ipset", "my_ipset1");
modparam("permissions", "declare_ipset", "my_ipset2=127.0.0.0/24;10.0.0.0/255.255.255.0");
	
route[TT2] {
	if (ip_is_trusted("$net", "$ip")) {
		xplog("L_E", "'%$ip' - TRUE\n");
	} else {
		xplog("L_E", "'%$ip' - FALSE\n");
	}
}

route[TT1] {
	xplog("L_E", "Testing netmask '%$net'\n");
	
	$ip = "s";   # source address
	route(TT2);
	
	$ip = "127.0.0.1";
	route(TT2);
	
	$ip = "127.0.0.2";
	route(TT2);
	
	$ip = "10.0.0.1";
	route(TT2);
	
	$ip = "11.0.0.1";
	route(TT2);
	
	$ip = "172.1.8.1";
	route(TT2);
	
	$ip = "192.168.1.1";
	route(TT2);
	
	$ip = "192.168.1.255";
	route(TT2);
	
	$ip = "192.168.2.1";
	route(TT2);
	
	$ip = "192.168.3.1";
	route(TT2);
	
	$ip = "192.168.4.97";
	route(TT2);
	
	$ip = "192.168.4.100";
	route(TT2);

	$ip = "[0:2:4:A:B:D:E:F301]";
	route(TT2);
	
	$ip = "[0:2:4:A:B:D:E:F401]";
	route(TT2);
	
	$ip = "[0:0:0:0:0:0:0:0]";
	route(TT2);
}
		
route[TEST] {
	$net = "0.0.0.0 128.2.3.4/1 127.0.128.16 [0:2:4:A:B:D:E:F301]";
	route(TT1);

	$net = "255.255.255.255/0"; # all IPv4 addresses, dentical to 0.0.0.0/0
	route(TT1);
	
	$net = "127.0.0.1/255.255.255.0";
	route(TT1);
	
	$net = "10.0.0.0/8";  # All type A addresses
	route(TT1);	         
	
	$net = "192.168.1.0/24";
	route(TT1);
	
	$net = "192.168.4.96/27";
	route(TT1);
	
	$net = "192.168.1.1/32"; # only one IP matches
	route(TT1);
	
	$net = "192.168.1.0/24,192.168.2.0/24";
	route(TT1);
	
	$net = "192.168.1.0/24,192.168.2.0/24,127.0.0.1/31";
	route(TT1);
	
	$net = "[0:0:0:0:0:0:0:0]/0";  # all IPv6 addresses
	route(TT1);
	
	$net = "[0:2:4:A:B:D:E:f300]/120";
	route(TT1);

	$net = "my_ipset1";
	route(TT1);

}
# the result is:

Testing netmask '0.0.0.0 128.2.3.4/1 127.0.128.16 [0:2:4:A:B:D:E:F301]'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - TRUE
'192.168.1.1' - TRUE
'192.168.1.255' - TRUE
'192.168.2.1' - TRUE
'192.168.3.1' - TRUE
'192.168.4.97' - TRUE
'192.168.4.100' - TRUE
'[0:2:4:A:B:D:E:F301]' - TRUE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '255.255.255.255/0'
's' - TRUE
'127.0.0.1' - TRUE
'127.0.0.2' - TRUE
'10.0.0.1' - TRUE
'11.0.0.1' - TRUE
'172.1.8.1' - TRUE
'192.168.1.1' - TRUE
'192.168.1.255' - TRUE
'192.168.2.1' - TRUE
'192.168.3.1' - TRUE
'192.168.4.97' - TRUE
'192.168.4.100' - TRUE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '127.0.0.1/24'
's' - FALSE
'127.0.0.1' - TRUE
'127.0.0.2' - TRUE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - FALSE
'192.168.1.255' - FALSE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '10.0.0.0/8'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - TRUE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - FALSE
'192.168.1.255' - FALSE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '192.168.1.0/24'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - TRUE
'192.168.1.255' - TRUE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '192.168.4.96/27'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - FALSE
'192.168.1.255' - FALSE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - TRUE
'192.168.4.100' - TRUE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '192.168.1.1/32'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - TRUE
'192.168.1.255' - FALSE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '192.168.1.0/24,192.168.2.0/24'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - TRUE
'192.168.1.255' - TRUE
'192.168.2.1' - TRUE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '192.168.1.0/24,192.168.2.0/24,127.0.0.1/31'
's' - FALSE
'127.0.0.1' - TRUE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - TRUE
'192.168.1.255' - TRUE
'192.168.2.1' - TRUE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - FALSE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
Testing netmask '[0:0:0:0:0:0:0:0]/0'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - FALSE
'192.168.1.255' - FALSE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - TRUE
'[0:2:4:A:B:D:E:F401]' - TRUE
'[0:0:0:0:0:0:0:0]' - TRUE
Testing netmask '[0:2:4:A:B:D:E:f300]/120'
's' - FALSE
'127.0.0.1' - FALSE
'127.0.0.2' - FALSE
'10.0.0.1' - FALSE
'11.0.0.1' - FALSE
'172.1.8.1' - FALSE
'192.168.1.1' - FALSE
'192.168.1.255' - FALSE
'192.168.2.1' - FALSE
'192.168.3.1' - FALSE
'192.168.4.97' - FALSE
'192.168.4.100' - FALSE
'[0:2:4:A:B:D:E:F301]' - TRUE
'[0:2:4:A:B:D:E:F401]' - FALSE
'[0:0:0:0:0:0:0:0]' - FALSE
}
	    </programlisting>
	</example>
    </section>
</section>
