1. Registrar Module
Jan Janak
FhG FOKUS
Copyright © 2003 FhG FOKUS
__________________________________________________________________
1.1. Overview
1.2. NAT Support In Registrar
1.3. Synchronizing UA Internal Clock
1.4. Processing +sip.instance parameter
1.5. Dependencies
1.6. Parameters
1.6.1. default_expires (integer)
1.6.2. min_expires (integer)
1.6.3. max_expires (integer)
1.6.4. default_q (integer)
1.6.5. append_branches (integer)
1.6.6. case_sensitive (integer)
1.6.7. desc_time_order (integer)
1.6.8. received_avp (integer)
1.6.9. received_param (integer)
1.6.10. max_contacts (integer)
1.6.11. retry_after (integer)
1.6.12. save_nat_flag (flagname or integer)
1.6.13. load_nat_flag (flagname or integer)
1.6.14. trust_received_flag (flagname or integer)
1.6.15. received_to_uri (boolean)
1.6.16. reply_code_attr (avp name)
1.6.17. reply_reason_attr (avp name)
1.6.18. contact_attr (avp name)
1.6.19. aor_attr (avp name)
1.6.20. server_id_attr (avp name)
1.7. Functions
1.7.1. save(domain)
1.7.2. save_noreply(domain)
1.7.3. lookup(domain)
1.7.4. registered(domain)
1.1. Overview
The module contains REGISTER processing logic.
1.2. NAT Support In Registrar
Registrar and usrloc modules implement NAT extensions that ensure that
SIP messages beging sent to registered contacts would use the same
socket (with the same IP address and port) on which the REGISTER that
registered the contact had been received. REGISTER messages generated
by user agents behind NAT ofter open a pinhole in the NAT because
REGISTER is usually the first message sent from the user agent to the
SIP server. A small example follows.
Let's suppose that we have a single SER instance listening on two ports
-- 5060 and 5090. Using a different port seems to be often necessary
because of broken SIP ALGs (Application Level Gateways) that are often
built into DSL routers or other devices. Such ALGs would mangle SIP
requests and responses coming to and from port 5060 and the only option
how to avoid such mangling is using a different port number.
Let's suppose that we have two UAs beind NAT, one of them is configured
to reach SER on port 5060, the other one is configured to use port 5090
(due to the reasons described above):
SER
+---------+
UA1 ---- NAT1 ----| 5060 |
| |
UA2 ---- NAT2 ----| 5090 |
+---------+
Registrar and usrloc would store the public IP of NAT with each
registered contact, thus it would know how to reach both user agents.
In addition to the public IP and port of the NAT device, registrar
would also remember the destination IP and port of the REGISTER request
(the IP and port used in SER). If registrar did not store this
information, it would not know what outbound socket it should use when
sending SIP messages to the registered contact. It would use the
default port number (often 5060) for such outgoing requests.
When an INVITE for UA1 comes, everything would work because UA1 used
port 5060 when registering and that is also the destination port in the
pinhole being kept open in NAT1:
SER
INVITE UA1 +--------+ INVITE UA1
UA1 ---- NAT1 <------------- | 5060 | <----------------
| |
UA2 ---- NAT2 | 5090 |
+--------+
When an INVITE for UA2 comes, SER would again use port 5060 as the
default outgoing source port number, but this time the message will be
dropped by NAT2, because the pinhole opened during the registration has
5060 as the destination port number:
SER
INVITE UA2 +--------+ INVITE UA2
UA1 ---- NAT1 +------ | 5060 | <---------------
| | |
UA2 ---- NAT2 X <----+ | 5090 |
+--------+
That is the reason why registrar and usrloc also need to remember the
IP and port used on the server side, that information would be used
later when forwarding INVITEs:
SER
+--------+ INVITE UA2
UA1 ---- NAT1 | 5060 | <---------------
INVITE UA2 | |
UA2 ---- NAT2 <------------- | 5090 |
+--------+
Note
The X next to NAT2 has disappeared in this picture which means that the
message will be lucky enough to make it through.
SER would encode this information into a SIP URI when saving contacts
in database and later, after restart of SER, this information will be
restored. The URI looks like:
sip:1.2.3.4:5060;dstip=5.6.7.8;dstport=5090
Where the hostname part is the public IP of the NAT, the port (5060) is
the port allocated by the NAT, "dstip" parameter is the IP used on SER
side and "dstport" parameter is the port number used on SER side during
registration. This information is later used to find the correct
outgoing socket in SER. If no such socket can be found (it can happen
if you reconfigure SER to use different ports or IPs), it will use the
default IP/port again.
1.3. Synchronizing UA Internal Clock
Many existing user agents support date and time synchronization from
the registrar. Registrar can append "Date" header field to the 200 OK
to REGISTER message received from the user agent. User agents that
support time synchronization would read the current date and time from
the header field and set internal clock to it. For example:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 62.240.165.98;branch=z9hG4bK3E66B9EB
CSeq: 1469 REGISTER
To: "1 1" <sip:jan@charon.ok2rab.cz>;tag=2bd21cbe8bf183397d829c66d62463e6.0aea
From: "1 1" <sip:jan@charon.ok2rab.cz>
Call-ID: 1767561454@62.240.165.98
Date: Fri, 02 Sep 2005 11:20:12 GMT
You can use append_time function from textops module to append the
header field to the reply. Put the function before save("location"); in
the configuration file.
Example 1. Adding Date header to Replies
if (uri == myself) {
if (method == "REGISTER") {
append_time();
save("location");
break;
};
};
1.4. Processing +sip.instance parameter
The GRUU extension for SIP (draft-ietf-sip-gruu-04) adds a new
parameter to the URI of the Contact header in the REGISTER request to
identify a UA instance globaly unique in the world. This is reached by
adding a globaly unqiue identifier, the so called sip instace, as a
parameter to the Contact URI within all REGISTER requests.
Example 2. A Contact header with sip instance parameter
Contact: <sip:nils@192.168.0.122:2532>;q=1.0;+sip.instance="<urn:uuid:6a66f3bd-5
b1f-448a-a8be-e29572ea3bee>"
By looking at this sip instance parameter the registrar can decide if
the incoming request is just an update of an existing Contact URI or if
a new Contact URI has to be added to the AOR of this account. Thus even
after a reboot of the UA the new REGISTER can be determined the request
as an update of an old, already existing entry.
The registrar module now looks for the sip instance parameter in the
Contact URI:
* If the sip instance parameter is not present in the URI of the
Contact header the algorithm stays the same as like before the GRUU
extension. Which means the registrar only compares the SIP URI from
the Contact header with the existing URIs for the AOR (account). If
exactly the same URI already exists the existing entry will be
updated, otherwise the URI will be added to the list.
* If the sip instace parameter is present in the URI of the Contact
header it will be first searched for an existing Contact with
exactly the same sip instance value. If an URI with exactly the
same sip instance value exists already in the database, the
existing entry will be replaced with the new value, no matter if
they differ or not. If no Contact with this sip instance value
exists a new entry for it will be added.
For example the following Contact would replace the Contact value from
the example above in the usrloc database because the sip instance value
is the same, although the Contact URI differs. Without the sip instance
this would have created two entries in the usrloc database.
Example 3. Different Contact with the same sip.instance
Contact: <sip:lando@192.168.0.2:2500>;q=1.0;+sip.instance="<urn:uuid:6a66f3bd-5b
1f-448a-a8be-e29572ea3bee>"
1.5. Dependencies
Registrar module depends on the following SER modules:
* usrloc - User Location Module.
* sl - Stateless Replies.
1.6. Parameters
1.6.1. default_expires (integer)
If the processed message contains neither Expires HFs nor expires
contact parameters, this value will be used for newly created usrloc
records. The parameter contains number of second to expire (for example
use 3600 for one hour).
Default value is 3600.
Example 4. Set default_expires parameter
...
modparam("registrar", "default_expires", 1800)
...
1.6.2. min_expires (integer)
The minimum expires value of a Contact, values lower than this minimum
will be automatically set to the minimum. Value 0 disables the
checking.
Default value is 60.
Example 5. Set min_expires parameter
...
modparam("registrar", "min_expires", 60)
...
1.6.3. max_expires (integer)
The maximum expires value of a Contact, values higher than this maximum
will be automatically set to the maximum. Value 0 disables the
checking.
Default value is 0.
Example 6. Set max_expires parameter
...
modparam("registrar", "max_expires", 120)
...
1.6.4. default_q (integer)
The parameter represents default q value for new contacts. Because ser
doesn't support float parameter types, the value in the parameter is
divided by 100 and stored as float. For example, if you want default_q
to be 0.38, use value 38 here.
Default value is 0.
Example 7. Set default_q parameter
...
modparam("registrar", "default_q", 100)
...
1.6.5. append_branches (integer)
The parameter controls how lookup function processes multiple contacts.
If there are multiple contacts for the given username in usrloc and
this parameter is set to 1, Request-URI will be overwritten with the
highest-q rated contact and the rest will be appended to sip_msg
structure and can be later used by tm for forking. If the parameter is
set to 0, only Request-URI will be overwritten with the highest-q rated
contact and the rest will be left unprocessed.
Default value is 1.
Example 8. Set append_branches parameter
...
modparam("registrar", "append_branches", 0)
...
1.6.6. case_sensitive (integer)
Note
This parameter was removed (obsolete since ser 2.0).
If set to 1 then AOR comparison will be case sensitive, if set to 0
then AOR comparison will be case insensitive--This is recommended.
Default value is 0.
Example 9. Set case_sensitive parameter
...
modparam("registrar", "case_sensitive", 1)
...
1.6.7. desc_time_order (integer)
Note
This parameter was removed (obsolete since ser 2.0).
If set to 1 then all contacts will be ordered in descending
modification time order. In this case the most recently updated/created
contact will be used.
Default value is 0.
Example 10. Set desc_time_order parameter
...
modparam("registrar", "desc_time_order", 1)
...
1.6.8. received_avp (integer)
Registrar will store the value of the AVP configured by this parameter
in the received column in the user location database. It will leave the
column empty if the AVP is empty. The AVP should contain a SIP URI
consisting of the source IP, port, and protocol of the REGISTER message
being processed.
Note
The value of this parameter should be the same as the value of
corresponding parameter of nathelper module.
Default value is 42.
Example 11. Set received_avp parameter
...
modparam("registrar", "received_avp", 43)
...
1.6.9. received_param (integer)
The name of the parameter that will be appended to Contacts of 200 OK
when the received URI was set by nathelper module.
Default value is "received".
Example 12. Set received_param parameter
...
modparam("registrar", "received_param", "rcv")
...
1.6.10. max_contacts (integer)
The parameter can be used to limit the number of contacts per AOR
(Address of Record) in the user location database. Value 0 disables the
check.
Default value is 0.
Example 13. Set max_contacts parameter
...
# Allow no more than 10 contacts per AOR
modparam("registrar", "max_contacts", 10)
...
1.6.11. retry_after (integer)
The registrar can generate 5xx reply to REGISTER in various situations.
It can, for example, happen when the max_contacts parameter is set and
the processing of REGISTER request would exceed the limit. In this case
the registrar would generate "503 Service Unavailable" response.
If you want to add the Retry-After header field in 5xx replies, set
this parameter to a value grater than zero (0 means do not add the
header field). See section 20.33 of RFC3261 for more details.
Default value is 0 (disabled).
Example 14. Set retry_after parameter
...
modparam("registrar", "retry_after", 30)
...
1.6.12. save_nat_flag (flagname or integer)
The contact will be marked as behind the NAT if this flag is set before
calling one of registrar save*() functions.
See also load_nat_flag.
The default value is 4 (flag number 4).
Example 15. Set save_nat_flag parameter
flags FLAG_NAT;
...
modparam("registrar", "save_nat_flag", "FLAG_NAT")
...
route{
...
if (nat_uac_test("19"))
setflag(FLAG_NAT);
...
}
1.6.13. load_nat_flag (flagname or integer)
This flag will be set by the registrar lookup*() functions if the
contact was marked as behind the NAT during its registration.
See also save_nat_flag.
The default value is 4 (flag number 4).
Example 16. Set load_nat_flag parameter
flags FLAG_NAT;
...
modparam("registrar", "load_nat_flag", "FLAG_NAT")
...
route{
...
if (lookup_contacts("location")) {
if (isflagset(FLAG_NAT)){
log(1, "natted contact");
# use rtpproxy a.s.o
}
...
}
...
}
1.6.14. trust_received_flag (flagname or integer)
If this flag is set, the received information added to the REGISTER
contacts on another machine (e.g. upstream proxy or replication peer)
by the fix_nated_register() function from the nathelper module (ser
version, under modules_s/) is trusted. If it is not set, it will be
ignored.
It is especially useful in REGISTER replication scenarios of registrars
behind a transparent load balancer (one IP) or a proxy / load balancer
that can make use of the original received information (in this case
combined with received_to_uri).
A contact with received information looks like:
<sip:foo@10.0.0.3:5060>;received="sip:1.2.3.4:3412;transport=TCP;dstip=
4.5.6.7;dstport=5060".
Besides the normal flags values (flag names or positive integers),
there are 2 special integer values: -1 and -2. If trust_received_flag
is set to -1 it is equivalent with disabling it globally (no contact
"received" parameter will be trusted, they will be all ignored). If set
to -2 all the contact "received" parameters will be trusted.
See also fix_nated_register() in ser nathelper version
(modules_s/nathelper).
The default value is -2 (always trust received), due to config
compatibility reasons with older ser versions.
Example 17. Set trust_received_flag parameter
flags FLAG_REPLICATED;
...
modparam("registrar", "trust_received_flag", "FLAG_REPLICATED")
...
route{
...
if (dst_ip==224.0.1.75 && method == "REGISTER") {
# REGISTER replicated on multicast (trusted)
setflag(FLAG_REPLICATED);
save_mem_nr("location");
...
}
...
}
1.6.15. received_to_uri (boolean)
If set the lookup*() functions will add a contact received information
to the uri, instead of using the contact received information as a
destination for the message.
The resulting message uri will look like:
<sip:contact>;received="sip:src_ip:src_port;transport=proto;dstip=iface
_ip;dstport=iface_port".
Is is useful when the registrar is behind some other proxy (e.g. load
balancer) and using Path is not desired. In this case the outer proxy
would have to look at the message uri, remove the "received" parameter
from the uri and use it as destination for the message.
The default value is 0 (off).
Example 18. Set received_to_uri parameter
...
modparam("registrar", "received_to_uri", 1)
# example uri for a message received on 1.2.3.4:5060 from 192.168.1.1:5060:
# <sip:foo@10.0.0.3>;received="sip:192.168.1.1:5060;dstip=1.2.3.4;dstport=5060"
1.6.16. reply_code_attr (avp name)
If one of the save*() functions that do not send a reply is used
(save_contacts_no_reply(), save_noreply() or save_mem_nr()), an AVP
with the given name will be set to the code of the reply that should be
send by other means.
See also reply_reason_attr and contact_attr.
The default value is "$code".
Example 19. Set reply_code_attr, reply_reason_attr parameters and
contact_attr
modparam("registrar", "reply_code_attr", "$repl_code")
modparam("registrar", "reply_reason_attr", "$repl_reason")
modparam("registrar", "contact_attr", "$contact")
...
route{
...
if (!save_noreply("location")) {
append_to_reply("$contact");
sl_send_reply($reply_code, $repl_reason);
}
...
}
1.6.17. reply_reason_attr (avp name)
See reply_code_attr above.
The default value is "$reason".
1.6.18. contact_attr (avp name)
See reply_code_attr above.
The default value is "$contact".
1.6.19. aor_attr (avp name)
If set to an AVP name, the AOR will be taken from this AVP, instead of
the message "To:" header (when using one of the save*() functions).
The default value is "$aor".
Example 20. Set aor_attr
modparam("registrar", "aor_attr", "$my_aor")
...
route{
...
if (src_ip==1.2.3.4)
$my_aor=@msg.header["From"];
save("location");
...
}
1.6.20. server_id_attr (avp name)
If set to an AVP name, the server ID associated to the contact will be
set to the AVP value. If not set or the AVP is not found, the server ID
will be set to the server_id of the current server.
The default value is "$server_id".
See also server_id (core parameter).
Example 21. Set server_id_attr
...
modparam("registrar", "server_id_attr", "$remote_server_id")
...
route{
...
if (dst_ip==224.0.1.75 && method == "REGISTER") {
# REGISTER replicated on multicast, use the originator server_id
# (saved in the custom SER-Server-ID header)
$remote_server_id = @msg.header["SER-Server-ID"];
setflag(FLAG_REPLICATED);
save_mem_nr("location");
...
}
...
}
1.7. Functions
1.7.1. save(domain)
The function processes a REGISTER message. It can add, remove or modify
usrloc records depending on Contact and Expires HFs in the REGISTER
message. On success, 200 OK will be returned listing all contacts that
are currently in usrloc. On an error, error message will be send with a
short description in reason phrase.
Meaning of the parameters is as follows:
* domain - Logical domain within registrar. If database is used then
this must be name of the table which stores the contacts.
Example 22. save usage
...
save("location");
...
1.7.2. save_noreply(domain)
Same as save() but it doesn't send a reply.
Meaning of the parameters is as follows:
* domain - Logical domain within registrar. If database is used then
this must be na e of the table which stores the contacts.
Example 23. save_noreply usage
...
save_noreply("location");
...
1.7.3. lookup(domain)
The functions extracts username from Request-URI and tries to find all
contacts for the username in usrloc. If there are no such contacts, -1
will be returned. If there are such contacts, Request-URI will be
overwritten with the contact that has the highest q value and
optionally the rest will be appended to the message (depending on
append_branches parameter value).
Meaning of the parameters is as follows:
* domain - Name of table that should be used for the lookup.
Example 24. lookup usage
...
lookup("location");
...
1.7.4. registered(domain)
The function returns true if the AOR in the Request-URI is registered,
false otherwise. The function does not modify the message being
process, it neither rewrites the Request-URI if a contact is found not
append branches.
Meaning of the parameters is as follows:
* domain - Name of table that should be used for the lookup.
Example 25. registered usage
...
if (registered("location")) {
sl_send_reply("100", "Trying");
...
};
...