1UID Domain Module
2
3Juha Heinanen
4
5   <jh@tutpro.com>
6
7   Copyright © 2002-2010 Juha Heinanen
8     __________________________________________________________________
9
10   Table of Contents
11
12   1. Admin Guide
13
14        1. Overview
15
16              1.1. Virtual Domains
17              1.2. Domain-level Configuration Attributes
18              1.3. Caching
19
20        2. Dependencies
21        3. Known Limitations
22        4. Parameters
23
24              4.1. db_url (string)
25              4.2. db_mode (integer)
26              4.3. domain_table (string)
27              4.4. did_col (string)
28              4.5. domain_col (string)
29              4.6. flags_col (string)
30              4.7. domattr_table (string)
31              4.8. domattr_did (string)
32              4.9. domattr_name (string)
33              4.10. domattr_type (string)
34              4.11. domattr_value (string)
35              4.12. domattr_flags (string)
36              4.13. load_domain_attrs (integer)
37
38        5. Functions
39
40              5.1. is_local(domain)
41              5.2. lookup_domain(attr_group, domain)
42
43        6. FIFO Interface
44
45              6.1. domain.reload
46              6.2. domain.dump
47
48        7. Internal API
49
50   List of Examples
51
52   1.1. Virtual Domain iptel.org
53   1.2. Database Representation of Virtual Domain
54   1.3. Table domain_attrs
55   1.4. Setting db_url parameter
56   1.5. Setting db_mode parameter
57   1.6. Setting domain_table parameter
58   1.7. Setting did_col parameter
59   1.8. Setting domain_col parameter
60   1.9. Setting flags_col parameter
61   1.10. Setting domattrs_table parameter
62   1.11. Setting domattrs_did parameter
63   1.12. Setting domattrs_name parameter
64   1.13. Setting domattrs_type parameter
65   1.14. Setting domattrs_value parameter
66   1.15. Setting domattrs_flags parameter
67   1.16. Setting load_domain_attrs parameter
68   1.17. is_uri_host_local_local usage
69   1.18. lookup_domain usage
70   1.19. Calling load_domain_api
71
72Chapter 1. Admin Guide
73
74   Table of Contents
75
76   1. Overview
77
78        1.1. Virtual Domains
79        1.2. Domain-level Configuration Attributes
80        1.3. Caching
81
82   2. Dependencies
83   3. Known Limitations
84   4. Parameters
85
86        4.1. db_url (string)
87        4.2. db_mode (integer)
88        4.3. domain_table (string)
89        4.4. did_col (string)
90        4.5. domain_col (string)
91        4.6. flags_col (string)
92        4.7. domattr_table (string)
93        4.8. domattr_did (string)
94        4.9. domattr_name (string)
95        4.10. domattr_type (string)
96        4.11. domattr_value (string)
97        4.12. domattr_flags (string)
98        4.13. load_domain_attrs (integer)
99
100   5. Functions
101
102        5.1. is_local(domain)
103        5.2. lookup_domain(attr_group, domain)
104
105   6. FIFO Interface
106
107        6.1. domain.reload
108        6.2. domain.dump
109
110   7. Internal API
111
1121. Overview
113
114   1.1. Virtual Domains
115   1.2. Domain-level Configuration Attributes
116   1.3. Caching
117
118   Domain modules, as the name suggests, implements support for multiple
119   independent virtual domains hosted on one SIP server. This is often
120   useful if you have multiple domain names and you want to make them all
121   work and appear as one. Alternatively you might find the module useful
122   if you want to run a shared SIP service for multiple independent
123   customers. The module stores all supported domains and associated
124   configuration in a database table. Most of the information can be
125   cached in memory for performance reasons.
126
1271.1. Virtual Domains
128
129   The domain module adds support for so-called virtual domains. A virtual
130   domain is just a collection of domain names and associated
131   configuration information identified by a unique identifier. We refer
132   to the domain identifier as DID elsewhere in the documentation. DID
133   stands for "Domain IDentifier". In traditional POST world the term DID
134   has a different meaning though. Please be aware that this is just pure
135   coincidence.
136
137   All domain names that belong to one virtual domain are interchangeable.
138   From SIP server's perspective there is no difference between them. They
139   can be used in SIP URIs interchangeably and the behavior of the SIP
140   server will not be affected. This is called "domain name normalization"
141   and it is one of the steps performed early during SIP message
142   processing.
143
144   The DID identifier can be anything. To the SIP server DIDs are just
145   opaque strings and what format you choose depends on your requirements
146   and the type of the setup. You can use numbers in smaller setups if the
147   size of the data is a concern. You can set the DID to the canonical
148   domain name of the domain. You can use RFC 4122 style UUIDs if your
149   setup is large and distributed. You can use anything as long as it can
150   be represented as string. The only requirement is that the identifier
151   of each virtual domain must be unique.
152
153   The following example illustrates how one virtual domain can be
154   represented. The iptel.org domain runs a public SIP service. The users
155   of the service can use SIP URIs of form sip:username@iptel.org. The SIP
156   service is distributed, there is a number of SIP servers. The SIP
157   servers are also available through a number of other domain names, such
158   as sip.iptel.org, proxy.iptel.org and so on. We created one virtual
159   domain in the domain module and added all such domain names to the
160   virtual domain:
161
162   Example 1.1. Virtual Domain iptel.org
163iptel
164  |
165  +---iptel.org
166  +---sip.iptel.org
167  +---proxy.iptel.org
168  +---213.192.59.75
169
170   In the example above, we chose "iptel" as the unique identifier for the
171   virtual domain. This identifier is permanent. It never changes. Over
172   time we may change domain names assigned to this virtual domain, but
173   this identifier never changes. The main reason why virtual domain
174   identifiers must never change is that because they are referenced from
175   other tables, for example the accounting table. The data in the
176   accounting table is long-lived, usually archived, and this ensures that
177   the data will still reference correct virtual domain, no matter what
178   domain names are assigned to it.
179
180   The virtual domain described above will be stored in the domain table
181   in the database:
182
183   Example 1.2. Database Representation of Virtual Domain
184+-------+-----------------+-------+
185| did   | domain          | flags |
186+-------+-----------------+-------+
187| iptel | iptel.org       |    33 |
188| iptel | sip.iptel.org   |    33 |
189| iptel | proxy.iptel.org |    33 |
190| iptel | 213.192.59.75   |    33 |
191+-------+-----------------+-------+
192
193   Because all domain names that belong to one particular virtual domain
194   are equal, it does not matter which domain name is used in the host
195   part of the SIP URI. Thus an imaginary user joe with SIP URI
196   sip:joe@iptel.org will also be reachable as sip:joe@sip.iptel.org,
197   sip:joe@proxy.iptel.org, and sip:joe@213.192.59.75. If we add a new
198   domain name to this virtual domain then joe will also be able to use
199   the new domain name in his SIP URI, without the need to change
200   anything.
201
2021.2. Domain-level Configuration Attributes
203
204   In addition to a number of domain names, each virtual domain can also
205   have extra configuration information associated with it. The
206   possibility to configure the SIP server sightly differently in each
207   virtual domain is, in fact, the main reason why we introduced the
208   concept of virtual domains. We wanted to have one SIP server which will
209   provide SIP service to multiple different customers and each of the
210   customers may have slightly different configuration requirements.
211   That's how domain-level configuration attributes were born.
212
213   Because the administrator of the SIP server seldom knows configuration
214   requirements in advance, we decided to implement a generic solution and
215   store all configuration options in named attributes. Named attributes
216   are just like variables, they have a name and they have a value.
217   Attributes are accessible from the configuration script of the SIP
218   server. Domain-level attributes are attributes that are associated with
219   a particular virtual domain. They can be used to store additional
220   configuration for the entire virtual domain, that is all users that
221   belong (or have SIP URI) in that particular virtual domain.
222   Domain-level attributes can be overridden be user-level attributes with
223   the same name configured for a particular user. In other words a domain
224   level attribute will only be effective if no user-level attribute with
225   the same name exists.
226
227   Domain-level attributes are stored in a separate table. The name of the
228   table is domain_attrs and it is defined as follows:
229
230   Example 1.3. Table domain_attrs
231+-------+------------------+------+-----+---------+-------+
232| Field | Type             | Null | Key | Default | Extra |
233+-------+------------------+------+-----+---------+-------+
234| did   | varchar(64)      | YES  | MUL | NULL    |       |
235| name  | varchar(32)      | NO   |     | NULL    |       |
236| type  | int(11)          | NO   |     | 0       |       |
237| value | varchar(255)     | YES  |     | NULL    |       |
238| flags | int(10) unsigned | NO   |     | 0       |       |
239+-------+------------------+------+-----+---------+-------+
240
241   Each attribute has name, type and value. A single attribute can have
242   multiple values and in that case it will occupy more rows in the table.
243   Each attribute is associated with a particular virtual domain using the
244   DID identifier. Domain-level attributes can contain just about
245   anything. It is a generic configuration mechanism and it is up to you
246   to define a list of attribute that are meaningful in your setup and use
247   those attributes in the routing part of the configuration file.
248
249   Attributes for a particular virtual-domain are made available to script
250   function by the lookup_domain function. This is the function that is
251   used to map domain names to DIDs. One of the side-effects of the
252   function is that it makes domain-level attributes available to script
253   function if a matching virtual domain is found.
254
255   When caching is enabled, all attributes from domain_attrs table are
256   cached in memory, just like virtual domain themselves. If you disable
257   caching then the domain module will attempt to load attributes from the
258   database each time you call lookup_domain. Attributes cached in memory
259   can be reloaded with the domain.reload management function.
260
2611.3. Caching
262
263   Domain module operates in caching or non-caching mode depending on
264   value of module parameter db_mode. In caching mode domain module reads
265   the contents of domain table into cache memory when the module is
266   loaded. After that domain table is re-read only when module is given
267   domain_reload fifo command. Any changes in domain table must thus be
268   followed by domain_reload command in order to reflect them in module
269   behavior. In non-caching mode domain module always queries domain table
270   in the database.
271
272   Caching is implemented using a hash table. The size of the hash table
273   is given by HASH_SIZE constant defined in domain_mod.h. Its "factory
274   default" value is 128. Caching mode is highly recommended if you want
275   to use domain-level attributes.
276
2772. Dependencies
278
279   The module depends on the following modules (in the other words the
280   listed modules must be loaded before this module):
281     * database - Any database module
282
2833. Known Limitations
284
285   There is an unlikely race condition on domain list update. If a process
286   uses a table, which is reloaded at the same time twice through FIFO,
287   the second reload will delete the original table still in use by the
288   process.
289
2904. Parameters
291
292   4.1. db_url (string)
293   4.2. db_mode (integer)
294   4.3. domain_table (string)
295   4.4. did_col (string)
296   4.5. domain_col (string)
297   4.6. flags_col (string)
298   4.7. domattr_table (string)
299   4.8. domattr_did (string)
300   4.9. domattr_name (string)
301   4.10. domattr_type (string)
302   4.11. domattr_value (string)
303   4.12. domattr_flags (string)
304   4.13. load_domain_attrs (integer)
305
3064.1. db_url (string)
307
308   This is URL of the database to be used.
309
310   Default value is "mysql://serro:47serro11@localhost/ser"
311
312   Example 1.4. Setting db_url parameter
313modparam("domain", "db_url", "mysql://ser:pass@db_host/ser")
314
3154.2. db_mode (integer)
316
317   Database mode. Value 0 means non-caching, 1 means caching is enabled.
318   It is highly recommended to enable caching if you want to use
319   domain-level attributes.
320
321   Default value is 1 (caching).
322
323   Example 1.5. Setting db_mode parameter
324modparam("domain", "db_mode", 0)   # Do not use caching
325
3264.3. domain_table (string)
327
328   Name of table containing names of local domains that the proxy is
329   responsible for. Local users must have in their SIP URI a host part
330   that is equal to one of the domains stored in this table.
331
332   Default value is "domain".
333
334   Example 1.6. Setting domain_table parameter
335modparam("domain", "domain_table", "new_name")
336
3374.4. did_col (string)
338
339   This is the name of the column in domain table that contains the unique
340   identifiers of virtual domains. Domains names found in this table are
341   arranged into virtual domains. Each virtual domain must have a unique
342   identifier and it can contain one or more domain names.
343
344   Default value is "did".
345
346   Example 1.7. Setting did_col parameter
347modparam("domain", "did_col", "did")
348
3494.5. domain_col (string)
350
351   Name of column containing domain names in the domain table.
352
353   Default value is "domain".
354
355   Example 1.8. Setting domain_col parameter
356modparam("domain", "domain_col", "domain")
357
3584.6. flags_col (string)
359
360   This is the name of the column in domain table which stores various
361   flags. Each row in the table has a bunch of generic flags that can be
362   used mark the row disabled, deleted, etc. The flags allow for more
363   flexible administration of the data in the database and they are
364   present in several other tables too.
365
366   Default value is "flags".
367
368   Example 1.9. Setting flags_col parameter
369modparam("domain", "flags_col", "domain")
370
3714.7. domattr_table (string)
372
373   This parameter can be used to configure the name of the table that is
374   used to store domain-level attributes. Domain level attributes are
375   attributes that are associated with a particular virtual domain. They
376   are typically used to store additional domain-wide settings that should
377   apply to all users who belong to the domain.
378
379   Default value is "domain_attrs".
380
381   Example 1.10. Setting domattrs_table parameter
382modparam("domain", "domattr_table", "domain_attrs")
383
3844.8. domattr_did (string)
385
386   Use this parameter to configure the name of the column in domain_attrs
387   table that is used to store the did of the virtual domain the attribute
388   belongs to. Normally there is no need to configure this parameter,
389   unless you want adapt to module to a different database schema.
390
391   Default value is "did".
392
393   Example 1.11. Setting domattrs_did parameter
394modparam("domain", "domattr_did", "did")
395
3964.9. domattr_name (string)
397
398   Use this parameter to configure the name of the column in domain_attrs
399   table that is used to store the name of the attribute. Normally there
400   is no need to configure this parameter, unless you want adapt to module
401   to a different database schema.
402
403   Default value is "name".
404
405   Example 1.12. Setting domattrs_name parameter
406modparam("domain", "domattr_name", "name")
407
4084.10. domattr_type (string)
409
410   Use this parameter to configure the name of the column in domain_attrs
411   table that is used to store the type of the attribute. Normally there
412   is no need to configure this parameter, unless you want adapt to module
413   to a different database schema.
414
415   Default value is "type".
416
417   Example 1.13. Setting domattrs_type parameter
418modparam("domain", "domattr_type", "type")
419
4204.11. domattr_value (string)
421
422   Use this parameter to configure the name of the column in domain_attrs
423   table that is used to store the value of the attribute. Normally there
424   is no need to configure this parameter, unless you want adapt to module
425   to a different database schema.
426
427   Default value is "value".
428
429   Example 1.14. Setting domattrs_value parameter
430modparam("domain", "domattr_value", "value")
431
4324.12. domattr_flags (string)
433
434   This is the name of the column in domain_attrs table which stores
435   various flags. Each row in the table has a bunch of generic flags that
436   can be used mark the row disabled, deleted, etc. The flags allow for
437   more flexible administration of the data in the database and they are
438   present in several other tables too. You do not have to touch this
439   parameter under normal circumstances.
440
441   Default value is "flags".
442
443   Example 1.15. Setting domattrs_flags parameter
444modparam("domain", "domattr_flags", "flags")
445
4464.13. load_domain_attrs (integer)
447
448   This parameter can be used to enable/disable user of domain-level
449   attributes. Domain-level attributes are variables that can be used to
450   store additional configuration that applies to the whole virtual domain
451   and all users within the virtual domain. Domain-level attributes are
452   stored in domain_attrs. If you set this parameter to a non-zero value
453   then the server will make domain-level attributes available to the
454   script every time you call function lookup_domain. If you set the
455   parameter to 0 then domain-level attributes will be ignored, the domain
456   module will not load them from the database and the lookup function
457   will not make them available to the script.
458
459   Default value is 0.
460
461   Example 1.16. Setting load_domain_attrs parameter
462modparam("domain", "load_domain_attrs", 1)
463
4645. Functions
465
466   5.1. is_local(domain)
467   5.2. lookup_domain(attr_group, domain)
468
4695.1. is_local(domain)
470
471   This function can be used to test whether a given domain name in
472   parameter belongs to one of the virtual domains defined in the domain
473   table. Such domain name is said to be local. The function returns 1 if
474   the domain name is found in the domain table and -1 otherwise.
475
476   The first parameter of the function can be anything that returns a
477   string with domain name. In its simplest form it can be a string with
478   domain name: is_local("iptel.org"). You can also test a domain name
479   stored in an attribute: is_local("$my_domain"). And finally you can
480   test a domain name present in the SIP message with selects:
481   is_local("@ruri.host").
482
483   Note: Unlike function lookup_domain, this function does not make domain
484   attributes of the virtual domain available to the script. Domain
485   attributes are simply ignored by this function.
486
487   Example 1.17. is_uri_host_local_local usage
488...
489if (is_local("@ruri.host")) {
490    /* Domain part of Request-URI is local */
491}
492...
493
4945.2. lookup_domain(attr_group, domain)
495
496   This is the main function of the domain module. It can be used to
497   implement support for virtual domains in the SIP server. Each virtual
498   domain is identified by a unique identifier (opaque string) and it can
499   have one or more associated domain names. Given a domain name in the
500   second parameter, this function finds the associated virtual domain
501   identifier (known as DID) and stores it in an attribute for later user.
502   In addition to that the function also loads all domain-level attributes
503   for the virtual domain and makes them available to the configuration
504   script.
505
506   The first parameter of the function identifies the group of attributes
507   where the DID and domain-level attributes shall be stored. The value of
508   the first parameter can be either "$fd" for the domain-level attribute
509   group that belongs to the calling party (From), or "$td" for the
510   domain-level attribute group that belongs to the called party
511   (Request-URI).
512
513   The value of the second parameter can be a simple string, an attribute
514   name, or a select. See the documentation of function is_local for more
515   details.
516
517   If a match is found then the DID of the virtual domain will be stored
518   either in $fd.did or in $td.did, depending on the value of the first
519   parameter. In addition to that domain-level attributes, if any, will be
520   available as either $fd.<name> or $td.</name>.
521
522   The function returns 1 when a matching virtual domain for the given
523   domain name was found and -1 otherwise.
524
525   The following example shows a typical use of the function. In a multi
526   domain setup, one has to typically figure out where the both the
527   calling and the called domains are local (i.e. configured on the server
528   as the domains the server is responsible for). This is typically done
529   by calling function lookup_domain twice, once with the hostname part of
530   the From header as parameter and secondly with the hostname part of the
531   Request-URI as parameter.
532
533   The type of the situation can be then determined from the value of
534   corresponding attributes ($td.did and $fd.did). A non-existing
535   attribute value indicates that the domain name is not local (it does
536   not belong to any virtual domain configured in the domain table).
537
538   Example 1.18. lookup_domain usage
539lookup_domain("$fd", "@from.uri.host");
540lookup_domain("$td", "@ruri.host");
541
542if (strempty($fd.did) && strempty($td.did)) {
543    # Neither the calling nor the called domain is local
544    # This is a relaying attempt which should be forbidden
545    sl_reply("403", "Relaying Forbidden");
546    drop;
547}
548if (strempty($fd.did) && $td.did) {
549    # The calling domain is not local and the called domain
550    # is local, this is an inbound call from a 3rd party
551    # user to one of local users
552}
553if ($fd.did && strempty($td.did)) {
554    # The calling domain is local and the called domain
555    # is not local, this is an outbound call from one of
556    # our users to a 3rd party user
557}
558if ($fd.did && $td.did) {
559    # Both the calling and the called domains are local,
560    # one of our local users calls another local user,
561    # either in the same virtual domain or in another
562    # virtual domain hosted on the same server
563}
564
5656. FIFO Interface
566
567   6.1. domain.reload
568   6.2. domain.dump
569
5706.1. domain.reload
571
572   Causes domain module to re-read the contents of domain table into cache
573   memory. If domain-level attributes are used then it will also re-load
574   the contents of the domain_attrs table in the memory cache.
575
5766.2. domain.dump
577
578   Causes domain module to dump hash indexes and domain names in its cache
579   memory.
580
5817. Internal API
582
583   The domain module has an internal API which can be used to access
584   additional functions of the module (i.e. functions that are normally
585   not available from the routing script). Currently the API exports only
586   the function is_domain_local. That function can be used to determine
587   whether a given domain name is on the list of locally configured domain
588   names.
589
590   If you want to use the internal API of domain module from your module
591   then you need to include the header file domain_api.h and call
592   load_domain_api first.
593
594   Example 1.19. Calling load_domain_api
595#include "../domain/domain_api.h"
596
597domain_api_t dom_api;
598
599if (load_domain_api(&dom_api) != 0) {
600    /* error */
601}
602
603   After that you can call function is_domain_local whose pointer is
604   stored in the initialized data structure:
605str tmp = STR_STATIC_INIT("mydomain.com");
606
607if (dom_api.is_domain_local(&tmp) == 1) {
608    /* Domain is local */
609} else {
610    /* Domain is not local or an error was encountered */
611}
612