瀏覽代碼

siputils: added new function is_first_hop()

- detect if it is first hop after original sender
- added section ids for functions, remove a duplicate content for
  is_rpid_user_e164()
Daniel-Constantin Mierla 12 年之前
父節點
當前提交
c8e928a2c7
共有 5 個文件被更改,包括 229 次插入155 次删除
  1. 94 94
      modules/siputils/README
  2. 52 52
      modules/siputils/doc/siputils_admin.xml
  3. 80 9
      modules/siputils/sipops.c
  4. 1 0
      modules/siputils/sipops.h
  5. 2 0
      modules/siputils/siputils.c

+ 94 - 94
modules/siputils/README

@@ -40,7 +40,7 @@ Edited by
 
 Gabriel Vasile
 
-   Copyright (c) 2008, 2005, 2003 1&1 Internet AG, FhG Fokus, Voice Sistem
+   Copyright © 2008, 2005, 2003 1&1 Internet AG, FhG Fokus, Voice Sistem
    SRL
      __________________________________________________________________
 
@@ -84,16 +84,16 @@ Gabriel Vasile
               4.14. decode_contact_header()
               4.15. cmp_uri(str1, str2)
               4.16. cmp_aor(str1, str2)
-              4.17. is_rpid_user_e164()
-              4.18. append_rpid_hf()
-              4.19. append_rpid_hf(prefix, suffix)
-              4.20. is_rpid_user_e164()
-              4.21. set_uri_user(uri, user)
-              4.22. set_uri_host(uri, host)
-              4.23. is_request()
-              4.24. is_reply()
-              4.25. is_gruu([uri])
-              4.26. is_supported(option)
+              4.17. append_rpid_hf()
+              4.18. append_rpid_hf(prefix, suffix)
+              4.19. is_rpid_user_e164()
+              4.20. set_uri_user(uri, user)
+              4.21. set_uri_host(uri, host)
+              4.22. is_request()
+              4.23. is_reply()
+              4.24. is_gruu([uri])
+              4.25. is_supported(option)
+              4.26. is_first_hop()
 
    List of Examples
 
@@ -122,16 +122,16 @@ Gabriel Vasile
    1.23. decode_contact_header usage
    1.24. cmp_uri usage
    1.25. cmp_aor usage
-   1.26. is_rpid_user_e164 usage
-   1.27. append_rpid_hf usage
-   1.28. append_rpid_hf(prefix, suffix) usage
-   1.29. is_rpid_user_e164 usage
-   1.30. set_uri_user usage
-   1.31. set_uri_host usage
-   1.32. is_request usage
-   1.33. is_reply usage
-   1.34. is_gruu() usage
-   1.35. is_supported() usage
+   1.26. append_rpid_hf usage
+   1.27. append_rpid_hf(prefix, suffix) usage
+   1.28. is_rpid_user_e164 usage
+   1.29. set_uri_user usage
+   1.30. set_uri_host usage
+   1.31. is_request usage
+   1.32. is_reply usage
+   1.33. is_gruu() usage
+   1.34. is_supported() usage
+   1.35. is_first_hop() usage
 
 Chapter 1. Admin Guide
 
@@ -173,16 +173,16 @@ Chapter 1. Admin Guide
         4.14. decode_contact_header()
         4.15. cmp_uri(str1, str2)
         4.16. cmp_aor(str1, str2)
-        4.17. is_rpid_user_e164()
-        4.18. append_rpid_hf()
-        4.19. append_rpid_hf(prefix, suffix)
-        4.20. is_rpid_user_e164()
-        4.21. set_uri_user(uri, user)
-        4.22. set_uri_host(uri, host)
-        4.23. is_request()
-        4.24. is_reply()
-        4.25. is_gruu([uri])
-        4.26. is_supported(option)
+        4.17. append_rpid_hf()
+        4.18. append_rpid_hf(prefix, suffix)
+        4.19. is_rpid_user_e164()
+        4.20. set_uri_user(uri, user)
+        4.21. set_uri_host(uri, host)
+        4.22. is_request()
+        4.23. is_reply()
+        4.24. is_gruu([uri])
+        4.25. is_supported(option)
+        4.26. is_first_hop()
 
 1. Overview
 
@@ -374,18 +374,18 @@ modparam("auth", "rpid_avp", "$avp(myrpid)")
    4.14. decode_contact_header()
    4.15. cmp_uri(str1, str2)
    4.16. cmp_aor(str1, str2)
-   4.17. is_rpid_user_e164()
-   4.18. append_rpid_hf()
-   4.19. append_rpid_hf(prefix, suffix)
-   4.20. is_rpid_user_e164()
-   4.21. set_uri_user(uri, user)
-   4.22. set_uri_host(uri, host)
-   4.23. is_request()
-   4.24. is_reply()
-   4.25. is_gruu([uri])
-   4.26. is_supported(option)
-
-4.1.  ring_insert_callid()
+   4.17. append_rpid_hf()
+   4.18. append_rpid_hf(prefix, suffix)
+   4.19. is_rpid_user_e164()
+   4.20. set_uri_user(uri, user)
+   4.21. set_uri_host(uri, host)
+   4.22. is_request()
+   4.23. is_reply()
+   4.24. is_gruu([uri])
+   4.25. is_supported(option)
+   4.26. is_first_hop()
+
+4.1. ring_insert_callid()
 
    Inserting the call-id in the internal list, which is checked when
    further replies arrive. Any 183 reply that is received during the
@@ -402,7 +402,7 @@ modparam("auth", "rpid_avp", "$avp(myrpid)")
 ring_insert_callid();
 ...
 
-4.2.  options_reply()
+4.2. options_reply()
 
    This function checks if the request method is OPTIONS and if the
    request URI does not contain an username. If both is true the request
@@ -430,7 +430,7 @@ if (uri==myself) {
 }
 ...
 
-4.3.  is_user(username)
+4.3. is_user(username)
 
    Check if the username in credentials matches the given username.
 
@@ -446,7 +446,7 @@ if (is_user("john")) {
 };
 ...
 
-4.4.  has_totag()
+4.4. has_totag()
 
    Check if To header field uri contains tag parameter.
 
@@ -459,7 +459,7 @@ if (has_totag()) {
 };
 ...
 
-4.5.  uri_param(param)
+4.5. uri_param(param)
 
    Find if Request URI has a given parameter with no value
 
@@ -475,7 +475,7 @@ if (uri_param("param1")) {
 };
 ...
 
-4.6.  uri_param(param,value)
+4.6. uri_param(param,value)
 
    Find if Request URI has a given parameter with matching value
 
@@ -492,7 +492,7 @@ if (uri_param("param1","value1")) {
 };
 ...
 
-4.7.  add_uri_param(param)
+4.7. add_uri_param(param)
 
    Add to RURI a parameter (name=value);
 
@@ -506,7 +506,7 @@ if (uri_param("param1","value1")) {
 add_uri_param("nat=yes");
 ...
 
-4.8.  get_uri_param(name, var)
+4.8. get_uri_param(name, var)
 
    Get the value of RURI parameter.
 
@@ -521,7 +521,7 @@ add_uri_param("nat=yes");
 get_uri_param("nat", "$var(nat)");
 ...
 
-4.9.  tel2sip(uri, hostpart, result)
+4.9. tel2sip(uri, hostpart, result)
 
    Converts URI in first param (pseudo variable or string) to SIP URI, if
    it is a tel URI. If conversion was done, writes resulting SIP URI to
@@ -553,7 +553,7 @@ tel2sip("$ru", $fd", "$ru");
 # $ru:  sip:+12345678;ext=200;[email protected];user=phone
 ...
 
-4.10.  is_e164(pseudo-variable)
+4.10. is_e164(pseudo-variable)
 
    Checks if string value of pseudo variable argument is an E164 number.
 
@@ -571,7 +571,7 @@ if (is_e164("$avp(i:705)") {
 };
 ...
 
-4.11.  is_uri_user_e164(pseudo-variable)
+4.11. is_uri_user_e164(pseudo-variable)
 
    Checks if userpart of URI stored in pseudo variable is E164 number.
 
@@ -588,7 +588,7 @@ if (is_uri_user_e164("$avp(i:705)") {
 };
 ...
 
-4.12.  encode_contact(encoding_prefix,hostpart)
+4.12. encode_contact(encoding_prefix,hostpart)
 
    This function will encode uri-s inside Contact header in the following
    manner sip:username:password@ip:port;transport=protocol goes
@@ -615,7 +615,7 @@ if (is_uri_user_e164("$avp(i:705)") {
 if (src_ip == 10.0.0.0/8) encode_contact("natted_client","1.2.3.4");
 ...
 
-4.13.  decode_contact()
+4.13. decode_contact()
 
    This function will decode the request URI. If the RURI is in the format
    sip:encoding_prefix*username*ip*port*protocol@hostpart it will be
@@ -633,7 +633,7 @@ if (src_ip == 10.0.0.0/8) encode_contact("natted_client","1.2.3.4");
 if (uri =~ "^sip:natted_client") { decode_contact(); }
 ...
 
-4.14.  decode_contact_header()
+4.14. decode_contact_header()
 
    This function will decode URIs inside Contact header. If the URI in the
    format sip:encoding_prefix*username*ip*port*protocol@hostpart it will
@@ -655,7 +655,7 @@ reply_route[2] {
 }
 ...
 
-4.15.  cmp_uri(str1, str2)
+4.15. cmp_uri(str1, str2)
 
    The function returns true if the two parameters matches as SIP URI.
 
@@ -669,7 +669,7 @@ if(cmp_uri("$ru", "sip:[email protected]"))
 }
 ...
 
-4.16.  cmp_aor(str1, str2)
+4.16. cmp_aor(str1, str2)
 
    The function returns true if the two parameters matches as AoR. The
    parameters have to be SIP URIs.
@@ -684,24 +684,7 @@ if(cmp_aor("[email protected]", "sip:kamailio@$fd"))
 }
 ...
 
-4.17.  is_rpid_user_e164()
-
-   The function checks if the SIP URI received from the database or radius
-   server and will potentially be used in Remote-Party-ID header field
-   contains an E164 number (+followed by up to 15 decimal digits) in its
-   user part. Check fails, if no such SIP URI exists (i.e. radius server
-   or database didn't provide this information).
-
-   This function can be used from REQUEST_ROUTE.
-
-   Example 1.26. is_rpid_user_e164 usage
-...
-if (is_rpid_user_e164()) {
-    # do something here
-};
-...
-
-4.18.  append_rpid_hf()
+4.17. append_rpid_hf()
 
    Appends to the message a Remote-Party-ID header that contains header
    'Remote-Party-ID: ' followed by the saved value of the SIP URI received
@@ -712,14 +695,14 @@ if (is_rpid_user_e164()) {
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE.
 
-   Example 1.27. append_rpid_hf usage
+   Example 1.26. append_rpid_hf usage
 ...
 append_rpid_hf();  # Append Remote-Party-ID header field
 ...
 
-4.19.  append_rpid_hf(prefix, suffix)
+4.18. append_rpid_hf(prefix, suffix)
 
-   This function is the same as Section 4.18, " append_rpid_hf()". The
+   This function is the same as Section 4.17, " append_rpid_hf()". The
    only difference is that it accepts two parameters--prefix and suffix to
    be added to Remote-Party-ID header field. This function ignores
    rpid_prefix and rpid_suffix parameters, instead of that allows to set
@@ -736,13 +719,13 @@ append_rpid_hf();  # Append Remote-Party-ID header field
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    BRANCH_ROUTE.
 
-   Example 1.28. append_rpid_hf(prefix, suffix) usage
+   Example 1.27. append_rpid_hf(prefix, suffix) usage
 ...
 # Append Remote-Party-ID header field
 append_rpid_hf("", ";party=calling;id-type=subscriber;screen=yes");
 ...
 
-4.20.  is_rpid_user_e164()
+4.19. is_rpid_user_e164()
 
    The function checks if the SIP URI received from the database or radius
    server and will potentially be used in Remote-Party-ID header field
@@ -752,68 +735,68 @@ append_rpid_hf("", ";party=calling;id-type=subscriber;screen=yes");
 
    This function can be used from REQUEST_ROUTE.
 
-   Example 1.29. is_rpid_user_e164 usage
+   Example 1.28. is_rpid_user_e164 usage
 ...
 if (is_rpid_user_e164()) {
     # do something here
 };
 ...
 
-4.21.  set_uri_user(uri, user)
+4.20. set_uri_user(uri, user)
 
    Sets userpart of SIP URI stored in writable pseudo variable 'uri' to
    value of pseudo variable 'user'.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.30. set_uri_user usage
+   Example 1.29. set_uri_user usage
 ...
 $var(uri) = "sip:user@host";
 $var(user) = "new_user";
 set_uri_user("$var(uri)", "$var(user)");
 ...
 
-4.22.  set_uri_host(uri, host)
+4.21. set_uri_host(uri, host)
 
    Sets hostpart of SIP URI stored in writable pseudo variable 'uri' to
    value of pseudo variable 'host'.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.31. set_uri_host usage
+   Example 1.30. set_uri_host usage
 ...
 $var(uri) = "sip:user@host";
 $var(host) = "new_host";
 set_uri_host("$var(uri)", "$var(host)");
 ...
 
-4.23.  is_request()
+4.22. is_request()
 
    Return true if the SIP message is a request.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.32. is_request usage
+   Example 1.31. is_request usage
 ...
 if (is_request()) {
         ...
 }
 ...
 
-4.24.  is_reply()
+4.23. is_reply()
 
    Return true if the SIP message is a reply.
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.33. is_reply usage
+   Example 1.32. is_reply usage
 ...
 if (is_reply()) {
         ...
 }
 ...
 
-4.25.  is_gruu([uri])
+4.24. is_gruu([uri])
 
    The function returns true if the uri is GRUU ('gr' parameter is
    present): 1 - pub-gruu; 2 - temp-gruu.
@@ -824,12 +807,12 @@ if (is_reply()) {
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.34. is_gruu() usage
+   Example 1.33. is_gruu() usage
 ...
 if(is_gruu()) { ... }
 ...
 
-4.26.  is_supported(option)
+4.25. is_supported(option)
 
    Function returns true if given option is listed in Supported header(s)
    (if any) of the request. Currently the following options are known:
@@ -837,7 +820,24 @@ if(is_gruu()) { ... }
 
    This function can be used from ANY_ROUTE.
 
-   Example 1.35. is_supported() usage
+   Example 1.34. is_supported() usage
 ...
 if (is_supported("outbound")) { ... }
 ...
+
+4.26. is_first_hop()
+
+   The function returns true if the proxy is first hop after the original
+   sender. For incoming SIP requests, it means there is only one Via
+   header. For incoming SIP replies, it means that top Record-Route URI is
+   'myself' and source address is not matching it (to avoid detecting in
+   case of local loops). Note that it does not detect spirals, which can
+   have the condition for replies true also in the case of additional SIP
+   reply receival.
+
+   This function can be used from ANY_ROUTE.
+
+   Example 1.35. is_first_hop() usage
+...
+if(is_first_hop()) { ... }
+...

+ 52 - 52
modules/siputils/doc/siputils_admin.xml

@@ -274,7 +274,7 @@ modparam("auth", "rpid_avp", "$avp(myrpid)")
 
 	<section>
 	<title>Functions</title>
-		<section>
+		<section id="siputils.f.ring_insert_callid">
 			<title>
 				<function moreinfo="none">ring_insert_callid()</function>
 			</title>
@@ -298,8 +298,8 @@ ring_insert_callid();
 ...
 				</programlisting>
 			</example>
-		</section>
-			<section>
+	</section>
+	<section id="siputils.f.options_reply">
 		<title>
 		<function moreinfo="none">options_reply()</function>
 		</title>
@@ -340,7 +340,7 @@ if (uri==myself) {
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.is_user">
 		<title>
 		<function moreinfo="none">is_user(username)</function>
 		</title>
@@ -368,7 +368,7 @@ if (is_user("john")) {
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.has_totag()">
 		<title>
 		<function moreinfo="none">has_totag()</function>
 		</title>
@@ -390,7 +390,7 @@ if (has_totag()) {
 		</example>
 	</section>
 	<section>
-		<title>
+		<title id="siputils.f.uri_param">
 		<function moreinfo="none">uri_param(param)</function>
 		</title>
 		<para>
@@ -417,7 +417,7 @@ if (uri_param("param1")) {
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.uri_param_value">
 		<title>
 		<function moreinfo="none">uri_param(param,value)</function>
 		</title>
@@ -449,7 +449,7 @@ if (uri_param("param1","value1")) {
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.add_uri_param">
 		<title>
 		<function moreinfo="none">add_uri_param(param)</function>
 		</title>
@@ -476,7 +476,7 @@ add_uri_param("nat=yes");
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.get_uri_param">
 		<title>
 		<function moreinfo="none">get_uri_param(name, var)</function>
 		</title>
@@ -505,7 +505,7 @@ get_uri_param("nat", "$var(nat)");
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.tel2sip">
 		<title>
 		<function moreinfo="none">tel2sip(uri, hostpart, result)</function>
 		</title>
@@ -553,7 +553,7 @@ tel2sip("$ru", $fd", "$ru");
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.is_e164">
 		<title>
 		<function moreinfo="none">is_e164(pseudo-variable)</function>
 		</title>
@@ -581,7 +581,7 @@ if (is_e164("$avp(i:705)") {
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.is_uri_user_e164">
 		<title>
 		<function moreinfo="none">is_uri_user_e164(pseudo-variable)</function>
 		</title>
@@ -608,7 +608,7 @@ if (is_uri_user_e164("$avp(i:705)") {
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.encode_contact">
 		<title>
 		<function moreinfo="none">encode_contact(encoding_prefix,hostpart)</function>
 		</title>
@@ -654,7 +654,7 @@ if (src_ip == 10.0.0.0/8) encode_contact("natted_client","1.2.3.4");
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.decode_contact">
 		<title>
 		<function moreinfo="none">decode_contact()</function>
 		</title>
@@ -681,7 +681,7 @@ if (uri =~ "^sip:natted_client") { decode_contact(); }
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.decode_contact_header">
 		<title>
 		<function moreinfo="none">decode_contact_header()</function>
 		</title>
@@ -711,7 +711,7 @@ reply_route[2] {
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.cmp_uri">
 		<title>
 		<function moreinfo="none">cmp_uri(str1, str2)</function>
 		</title>
@@ -735,7 +735,7 @@ if(cmp_uri("$ru", "sip:[email protected]"))
 		</example>
 	</section>
 
-	<section>
+	<section id="siputils.f.cmp_aor">
 		<title>
 		<function moreinfo="none">cmp_aor(str1, str2)</function>
 		</title>
@@ -759,32 +759,7 @@ if(cmp_aor("[email protected]", "sip:kamailio@$fd"))
 </programlisting>
 		</example>
 	</section>
-	<section>
-		<title>
-			<function moreinfo="none">is_rpid_user_e164()</function>
-		</title>
-		<para>
-		The function checks if the SIP URI received from the database or 
-		radius server and will potentially be used in Remote-Party-ID header 
-		field contains an E164 number (+followed by up to 15 decimal digits) 
-		in its user part.  Check fails, if no such SIP URI exists 
-		(i.e. radius server or database didn't provide this information).
-		</para>
-		<para>
-		This function can be used from REQUEST_ROUTE.
-		</para>
-		<example>
-		<title>is_rpid_user_e164 usage</title>
-		<programlisting format="linespecific">
-...
-if (is_rpid_user_e164()) {
-    # do something here
-};
-...
-</programlisting>
-		</example>
-	</section>
-	<section id="append-rpid-hf-no-params">
+	<section  id="siputils.f.append_rpid_hf">
 		<title>
 			<function moreinfo="none">append_rpid_hf()</function></title>
 		<para>
@@ -807,13 +782,13 @@ append_rpid_hf();  # Append Remote-Party-ID header field
 </programlisting>
 		</example>
 	</section>
-	<section id="append-rpid-hf-params">
+	<section id="siputils.f.append_rpid_hf_params">
 		<title>
 			<function moreinfo="none">append_rpid_hf(prefix, suffix)</function>
 		</title>
 		<para>
 		This function is the same as 
-		<xref linkend="append-rpid-hf-no-params"/>. The only difference is
+		<xref linkend="siputils.f.append_rpid_hf"/>. The only difference is
 		that it accepts two parameters--prefix and suffix to be added to 
 		Remote-Party-ID header field. This function ignores rpid_prefix and 
 		rpid_suffix parameters, instead of that allows to set them in every 
@@ -850,7 +825,7 @@ append_rpid_hf("", ";party=calling;id-type=subscriber;screen=yes");
 		</example>
 	</section>
 	<section>
-		<title>
+		<title id="siputils.f.is_rpid_user_e164">
 			<function moreinfo="none">is_rpid_user_e164()</function>
 		</title>
 		<para>
@@ -874,7 +849,7 @@ if (is_rpid_user_e164()) {
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.set_uri_user">
 		<title>
 			<function moreinfo="none">set_uri_user(uri, user)</function>
 		</title>
@@ -896,7 +871,7 @@ set_uri_user("$var(uri)", "$var(user)");
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.set_uri_host">
 		<title>
 			<function moreinfo="none">set_uri_host(uri, host)</function>
 		</title>
@@ -918,7 +893,7 @@ set_uri_host("$var(uri)", "$var(host)");
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.is_request">
 		<title>
 		<function moreinfo="none">is_request()</function>
 		</title>
@@ -939,7 +914,7 @@ if (is_request()) {
 </programlisting>
 		</example>
 	</section>
-	<section>
+	<section id="siputils.f.is_reply">
 		<title>
 		<function moreinfo="none">is_reply()</function>
 		</title>
@@ -960,7 +935,7 @@ if (is_reply()) {
 </programlisting>
 		</example>
 	</section>
-	<section id="is-gruu">
+	<section id="siputils.f.is_gruu">
 		<title>
 			<function moreinfo="none">is_gruu([uri])</function>
 		</title>
@@ -989,7 +964,7 @@ if(is_gruu()) { ... }
 </programlisting>
 		</example>
 	</section>
-	<section id="is-supported">
+	<section id="siputils.f.is_supported">
 		<title>
 			<function moreinfo="none">is_supported(option)</function>
 		</title>
@@ -1009,6 +984,31 @@ if(is_gruu()) { ... }
 ...
 if (is_supported("outbound")) { ... }
 ...
+</programlisting>
+		</example>
+	</section>
+	<section id="siputils.f.is_first_hop">
+		<title>
+			<function moreinfo="none">is_first_hop()</function>
+		</title>
+		<para>
+		The function returns true if the proxy is first hop after the
+		original sender. For incoming SIP requests, it means there is only
+		one Via header. For incoming SIP replies, it means that top
+		Record-Route URI is 'myself' and source address is not matching it
+		(to avoid detecting in case of local loops). Note that it does not
+		detect spirals, which can have the condition for replies true also
+		in the case of additional SIP reply receival.
+		</para>
+		<para>
+		This function can be used from ANY_ROUTE.
+		</para>
+		<example>
+		<title>is_first_hop() usage</title>
+		<programlisting format="linespecific">
+...
+if(is_first_hop()) { ... }
+...
 </programlisting>
 		</example>
 	</section>

+ 80 - 9
modules/siputils/sipops.c

@@ -34,6 +34,10 @@
 #include "../../mod_fix.h"
 #include "../../parser/parse_uri.h"
 #include "../../parser/parse_supported.h"
+#include "../../parser/parse_rr.h"
+#include "../../ip_addr.h"
+#include "../../resolve.h"
+#include "../../forward.h"
 #include "../../lib/kcore/cmpapi.h"
 
 #include "sipops.h"
@@ -118,16 +122,83 @@ int w_is_gruu(sip_msg_t *msg, char *uri1, char *p2)
 
 int w_is_supported(sip_msg_t *msg, char *_option, char *p2)
 {
-    unsigned long option;
+	unsigned long option;
 
-    option = (unsigned long)_option;
+	option = (unsigned long)_option;
 
-    if (parse_supported(msg) < 0)
-	return -1;
+	if (parse_supported(msg) < 0)
+		return -1;
 
-    if ((((struct option_tag_body*)msg->supported->parsed)->option_tags_all &
-	 option) == 0)
-	return -1;
-    else
-	return 1;
+	if ((((struct option_tag_body*)msg->supported->parsed)->option_tags_all &
+				option) == 0)
+		return -1;
+	else
+		return 1;
+}
+
+
+int w_is_first_hop(sip_msg_t *msg, char *p1, char *p2)
+{
+	int ret;
+	rr_t* r = NULL;
+	sip_uri_t puri;
+	struct ip_addr *ip;
+
+	if(msg==NULL)
+		return -1;
+
+	if(msg->first_line.type == SIP_REQUEST) {
+		if (parse_headers( msg, HDR_VIA2_F, 0 )<0
+				|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
+		{
+			/* sip request: if more than one via, then not first hop */
+			/* no second via or error */
+			LM_DBG("no 2nd via found - first hop\n");
+			return 1;
+		}
+		return -1;
+	} else if(msg->first_line.type == SIP_REPLY) {
+		/* sip reply: if top record-route is myself
+		 * and not received from myself (loop), then is first hop */
+		if (parse_headers( msg, HDR_EOH_F, 0 )<0) {
+			LM_DBG("error parsing headers\n");
+			return -1;
+		}
+		if(msg->record_route==NULL) {
+			LM_DBG("no record-route header - first hop\n");
+			return 1;
+		}
+		if(parse_rr(msg->record_route)<0) {
+			LM_DBG("failed to parse first record-route header\n");
+			return -1;
+		}
+		r = (rr_t*)msg->record_route->parsed;
+		if(parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &puri)<0) {
+			LM_DBG("failed to parse uri in first record-route header\n");
+			return -1;
+		}
+		if (((ip = str2ip(&(puri.host))) == NULL)
+				&& ((ip = str2ip6(&(puri.host))) == NULL)) {
+			LM_DBG("uri host is not an ip address\n");
+			return -1;
+		}
+		ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
+				(puri.transport_val.s)?puri.proto:0);
+		if(ret!=1) {
+			LM_DBG("top record route uri is not myself\n");
+			return -1;
+		}
+		if (ip_addr_cmp(ip, &(msg->rcv.src_ip))
+				&& ((msg->rcv.src_port == puri.port_no)
+					|| ((puri.port.len == 0) && (msg->rcv.src_port == 5060)))
+				&& (puri.proto==msg->rcv.proto
+					|| (puri.proto==0 && msg->rcv.proto==PROTO_UDP)) ) {
+			LM_DBG("source address matches top record route uri - loop\n");
+			return -1;
+		}
+		/* todo - check spirals */
+		return 1;
+	} else {
+		return -1;
+	}
 }

+ 1 - 0
modules/siputils/sipops.h

@@ -40,5 +40,6 @@ int w_cmp_uri(struct sip_msg *msg, char *uri1, char *uri2);
 int w_cmp_aor(struct sip_msg *msg, char *uri1, char *uri2);
 int w_is_gruu(sip_msg_t *msg, char *uri1, char *p2);
 int w_is_supported(sip_msg_t *msg, char *_option, char *p2);
+int w_is_first_hop(sip_msg_t *msg, char *uri1, char *p2);
 
 #endif

+ 2 - 0
modules/siputils/siputils.c

@@ -173,6 +173,8 @@ static cmd_export_t cmds[]={
 		0, ANY_ROUTE},
 	{"is_supported",  (cmd_function)w_is_supported,                    1, fixup_option,
 		0, ANY_ROUTE},
+	{"is_first_hop",  (cmd_function)w_is_first_hop,                    0, 0,
+		0, ANY_ROUTE},
 	{0,0,0,0,0,0}
 };