diff --git a/doc/siproxd.conf.example b/doc/siproxd.conf.example
index e7b5701..7733668 100644
--- a/doc/siproxd.conf.example
+++ b/doc/siproxd.conf.example
@@ -325,8 +325,9 @@ plugin_shortdial_entry = 17474745000
######################################################################
# Plugin_defaulttarget
#
+# Log redirects to syslog
plugin_defaulttarget_log = 1
# target must be a full SIP URI with the syntax
-# sip:user@hst[:port]
+# sip:user@host[:port]
plugin_defaulttarget_target = sip:internal@dddd:port
diff --git a/doc/siproxd_guide.sgml b/doc/siproxd_guide.sgml
index 8cba4d2..0749077 100644
--- a/doc/siproxd_guide.sgml
+++ b/doc/siproxd_guide.sgml
@@ -47,7 +47,7 @@
0.7.1
2008-01-27
tries@users.sourceforge.net
- Plugin API
+ Plug-in API
@@ -308,11 +308,6 @@ daemonize = 1
silence_log = 0
-
-
- Siproxd can log call establishment to syslog.
-
-log_calls = 1
If siproxd is started as root, it can drop the root
@@ -468,23 +463,6 @@ debug_port = 0
#outbound_domain_name = freenet.de
#outbound_domain_host = proxy.for.domain.freende.de
#outbound_domain_port = 5060
-
-
- Quick-Dial "Plug-in":
- ability to define quick dial numbers that can be accessed by
- dialing "*nn" from a local phone. 'nn' corresponds to the entry number
- pi_shortdial_entry) below. The '*' character can be chosen freely
- (pi_shortdial_akey).
- Note: To call a real number like "*1234" you would have to dial
- "**1234"
-
-pi_shortdial_enable = 1
-pi_shortdial_akey = *
-#
-# *01 sipphone echo test
-pi_shortdial_entry = 17474743246
-# *02 sipphone welcome message
-pi_shortdial_entry = 17474745000
@@ -497,6 +475,7 @@ pi_shortdial_entry = 17474745000
-h, --help help
-d, --debug <pattern> set debug-pattern
-c, --config <cfgfile> use the specified config file
+-p, --pid-file <pidfile> create pid file at <pidfile>
These options take precedence over the values configured
in the configuration file.
@@ -527,31 +506,31 @@ pi_shortdial_entry = 17474745000
Chroot() Jail
Create chroot jail
- What files must be present?
+ What files must be present? To be completed!
-
-
+
+
- Plugins
+ Plug-ins
-
+
- Plugin API
- Siproxd plugins are dynamic loadable libraries and must provide
+ Plug-in API
+ Siproxd plug-ins are dynamic loadable libraries and must provide
3 functions towards siproxd:
+
int plugin_init(plugin_def_t *plugin_def);
int plugin_process(int stage, sip_ticket_t *ticket);
int plugin_end(plugin_def_t *plugin_def);
-
The plugin_init function is called when
- the plugin is loaded during startup of siproxd. The plugin must
- defined the following 4 fields of the plugin_def structure:
+ the plug-in is loaded during startup of siproxd. The plug-in must
+ define the following 4 fields of the plugin_def structure:
api_version
name
@@ -560,21 +539,23 @@ int plugin_end(plugin_def_t *plugin_def);
Example code fragment:
+
-/* API version number of siproxd that this plugin is built against.
+/* API version number of siproxd that this plug-in is built against.
* This constant will change whenever changes to the API are made
- * that require adaptions in the plugin. */
+ * that require adaptions in the plug-in. */
plugin_def->api_version=SIPROXD_API_VERSION;
-/* Name and descriptive text of the plugin */
+/* Name and descriptive text of the plug-in. Those item MUST NOT be
+ on the stack but either allocated via malloc (and then freed
+ of course) or a static string in the plug-in. */
plugin_def->name=strdup("plugin_demo");
plugin_def->desc=strdup("This is just a demo plugin without any purpose");
/* Execution mask - during what stages of SIP processing shall
- * the plugin be called. */
+ * the plug-in be called. */
plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET|PLUGIN_PRE_PROXY;
-
The plugin_process function is called at
the requested SIP processing stages (see 'execution mask').
@@ -582,15 +563,16 @@ plugin_def->exe_mask=PLUGIN_DETERMINE_TARGET|PLUGIN_PRE_PROXY;
The plugin_end function is called at
- shutdown of siproxd and gives the plugin the opportunity
+ shutdown of siproxd and gives the plug-in the opportunity
to clean up and properly shutdown itself.
Note: The previously allocated 'name' and 'desc' must be
- freed by the plugin.
+ freed by the plug-in. If you did use a static string then of
+ course you must not try to free() anything.
Minimum required clean up procedure:
int plugin_end(plugin_def_t *plugin_def){
- /* free my allocated rescources */
+ /* free my allocated rescources (if allocated via malloc only) */
if (plugin_def->name) {free(plugin_def->name); plugin_def->name=NULL;}
if (plugin_def->desc) {free(plugin_def->desc); plugin_def->desc=NULL;}
return STS_SUCCESS;
@@ -598,49 +580,130 @@ int plugin_end(plugin_def_t *plugin_def){
- For a simple example refer to the simple demonstration plugin
+ For a simple example refer to the simple demonstration plug-in
plugin_demo.
- .
+
+
+ Each plug-in can have its own set of configuration parameters
+ in siproxd.conf. The plug-in has to define
+ a cfgopts_t structure and call
+ read_config during its initialization. Look at
+ plugin_demo for a simple example. The naming of
+ the config parameters is by definition
+ plugin_name_option.
+
-
+
- Available Plugins
- The following plugins are provided with siproxd:
+ Available Plug-ins
+ The following plug-ins are provided with siproxd:
plugin_demo
- Demo plugin. Provides the basic framework to
- be used for plugins.
+ Demo plug-in. Provides the basic framework to
+ be used for plug-ins.
+
+ plugin_logcall
+ Very simplistic call logging to syslog.
plugin_shortdial
Quick Dial feature.
+ plugin_defaulttarget
+ Incoming calls to a non-existing UA are
+ redirected to a specific target (catch-all).
+
- Some of the plugins are described in more detail in the
+ Some of the plug-ins are described in more detail in the
following chapters.
-
-
-
-
- Quick Dial
-
- Since 0.5.12, Siproxd includes a Quick-Dial feature. This
- allows you to define SIP numbers that can be accessed by
- using a shortctu (like "*nn") from any local SIP phone.
- For example, the following lines in your siproxd.conf will
- configure 2 Quick-Dial numbers:
+
+
+
+ Demo Plug-in
+ Name: plugin_demo
+ Purpose: To be used as skeletton for your own plug-ins.
+ Configuration options:
-# *01 sipphone echo test
-pi_shortdial_entry = 17474743246
-# *02 sipphone welcome message
-pi_shortdial_entry = 17474745000
+plugin_demo_string = This_is_a_string_passed_to_the_demo_plugin
- The numbering starts with "1" ("*01") and every following
- "pi_shortdial_entry" entry will allocate the following position.
- Curently it is not possible to freely assign the positions.
+ Description:
+ This plug-in can be used as framework for your own plug-ins.
+ It contains the required code for the API and also shows
+ how to load plug-in specific configuration parameters.
+
+
+
+
+
+
+ Call Logging Plug-in
+ Name: plugin_logcall
+ Purpose: Does a very simplistic call logging to syslog.
+ Configuration options:
+
+none
+
+ Description:
+ XXXXXXXXXXXXXXXXxThe numbering starts with "1" ("*01") and every following
+ "plugin_shortdial_entry" entry will allocate the following position.
+ It is not possible to freely assign the positions.
+
+
+
+
+
+ Short Dial Plug-in
+ Name: plugin_shortdial.c
+ Purpose: Provides a quick-Dial feature.
+
+
+# The first character is the "key", the following characters give
+# the length of the number string. E.g. "*00" allows speed dials
+# from *01 to *99. (the number "*100" will be passed through unprocessed)
+plugin_shortdial_akey = *00
+#
+# *01 sipphone echo test
+plugin_shortdial_entry = 17474743246
+# *02 sipphone welcome message
+plugin_shortdial_entry = 17474745000
+
+ Description:
+ Allows the definition of quick dial entries. E.g.
+ *01 to *99 can be defined to redirect the caller.
+ Note: Currently only the user part (phone number) can
+ be replaced, the domain part will not be changed (means
+ a short dial tarket of sip:111@other.domain.com will
+ not work). The '*' character can be chosen freely
+ (plugin_shortdial_akey).
+ Note: To call a real number like "*12" you have to dial
+ "**12"
+
+
+
+
+
+
+ Default Target Plug-in
+ Name: plugin_defaulttarget
+ Purpose: Incoming calls to non-existing local UAs are
+ redirected to another SIP URI.
+ Configuration options:
+
+# Log redirects to syslog
+plugin_defaulttarget_log = 1
+# target must be a full SIP URI with the syntax
+# sip:user@host[:port]
+plugin_defaulttarget_target = sip:defaulttarget@some.sip.domain:port
+
+ Description:
+ Incoming SIP calls directed to a non-existing (registered)
+ local UA will be redirected to another target. This basically
+ implements a catch-all feature. The new target can be any SIP
+ URI and is not required to be local.
+
@@ -734,14 +797,14 @@ pi_shortdial_entry = 17474745000
-
-
+
+
Sample Configurations
Check also the FAQ in the siproxd package.
-
-
-
+
+
+
The "Standard Scenario"
Scenario:
@@ -783,9 +846,9 @@ ipchains -A input --proto udp --dport 7070:7089 -j ACCEPT
incoming RTP traffic).
-
-
-
+
+
+
GS BT-100 behind NAT Router running Siproxd
Scenario:
@@ -812,7 +875,6 @@ hosts_allow_reg = 10.0.0.0/24
sip_listen_port = 5060
daemonize = 1
silence_log = 1
-log_calls = 1
user = siproxd
registration_file = /var/lib/siproxd_registrations
pid_file = /var/run/siproxd/siproxd.pid
@@ -858,9 +920,9 @@ Send DTMF: via RTP (RFC2833)
-
-
-
+
+
+
GS BT-100 with Siproxd running "in front of" a NAT router
Scenario:
@@ -894,7 +956,6 @@ hosts_allow_reg = 10.0.0.0/24
sip_listen_port = 5060
daemonize = 1
silence_log = 1
-log_calls = 1
user = siproxd
registration_file = /var/lib/siproxd_registrations
pid_file = /var/run/siproxd/siproxd.pid
@@ -940,9 +1001,9 @@ Send DTMF: via RTP (RFC2833)
-
-
-
+
+
+
Transparent SIP Proxy
Scenario:
@@ -971,7 +1032,6 @@ hosts_allow_reg = 10.0.0.0/24
sip_listen_port = 5060
daemonize = 1
silence_log = 1
-log_calls = 1
user = siproxd
registration_file = /var/lib/siproxd_registrations
pid_file = /var/run/siproxd/siproxd.pid
@@ -994,9 +1054,9 @@ iptables -A INPUT -m udp -p udp -i ppp0 --dport 7070:7089 -j ACCEPT
-
-
-
+
+
+
Masquerading an Asterisk box
Scenario:
@@ -1029,7 +1089,6 @@ hosts_allow_reg = 10.0.0.0/24
sip_listen_port = 5060
daemonize = 1
silence_log = 1
-log_calls = 1
user = siproxd
registration_file = /var/lib/siproxd_registrations
pid_file = /var/run/siproxd/siproxd.pid
diff --git a/src/proxy.c b/src/proxy.c
index 28213ea..9d37b91 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -383,6 +383,11 @@ sts=sip_obscure_callid(ticket);
*/
} else {
/* get the destination from the SIP URI */
+/*&&&& Here, the SRV record lookup magic must go.
+In a first implementation we may just try to get the lowest priority,
+max weighted '_sip._udp.domain' entry and port number.
+No load balancing and no failover are supported with this.
+&&&*/
sts = get_ip_by_host(url->host, &sendto_addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]",
@@ -667,7 +672,7 @@ sts=sip_obscure_callid(ticket);
/*&&&& priority probably should be:
* 1) Route header
* 2) fixed outbound proxy
- * 3) SIP URI
+ * 3) Via header
*/
/*
* check if we need to send to an outbound proxy
diff --git a/src/resolve.c b/src/resolve.c
index 708f94f..580d22f 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -35,36 +35,44 @@ static char const ident[]="$Id$";
/* local functions */
-static int _resolve(char *name, int proto, int type,
+static int _resolve(char *name, int class, int type,
char *dname, int dnamelen, int *port);
-#define PROTO_UDP 1
-#define PROTO_TCP 2
-
/*
* perform a SRV record lookup
+ *
+ * name name of service
+ * dname return
+ * dnamelen length of return buffer
+ * port port number of service
*/
-int resolve_SRV(char *name, int proto, char *dname, int dnamelen, int *port) {
- return _resolve(name, proto, T_SRV, dname, dnamelen, port);
+int resolve_SRV(char *name, char *dname, int dnamelen, int *port) {
+ char nname[256];
+ snprintf(nname, sizeof(nname), "_sip._udp.%s", name);
+ return _resolve(name, C_IN, T_SRV, dname, dnamelen, port);
}
+#if 0
/*
* perform a NAPTR lookup
+ *
+ * name name of service
+ * dname return
+ * dnamelen length of return buffer
*/
int resolve_NAPTR(char *name, char *dname, int dnamelen) {
int port=0;
- return _resolve(name, 0, T_NAPTR, dname, dnamelen, &port);
+ return _resolve(name, C_ANY, T_NAPTR, dname, dnamelen, &port);
}
-
+#endif
/*
* query the DNS for a specific record type
*/
-static int _resolve(char *name, int proto, int type,
+static int _resolve(char *name, int class, int type,
char *dname, int dnamelen, int *port) {
int sts;
- int class=C_ANY;
// message buffer
unsigned char msg[PACKETSZ];
@@ -90,7 +98,6 @@ static int _resolve(char *name, int proto, int type,
dname[0]='\0';
*port=0;
-
// issue request
sts=res_query(name, class, type, msg, msglen);
if (sts<0) {
@@ -141,7 +148,44 @@ static int _resolve(char *name, int proto, int type,
mptr += sizeof(short);
xptr = mptr;
mptr += j;
- if( ty == T_NAPTR ) {
+ if( ty == T_SRV ) {
+ u_short pr;
+ u_short we;
+ u_short po;
+ usp = (unsigned short *)xptr;
+ pr = ntohs( *usp );
+ xptr += sizeof( short );
+ usp = (unsigned short *)xptr;
+ we = ntohs( *usp );
+ xptr += sizeof( short );
+ usp = (unsigned short *)xptr;
+ po = ntohs( *usp );
+ xptr += sizeof( short );
+ j = dn_expand( msg, msg + PACKETSZ, xptr, tmpname, MAXDNAME );
+ if( j < 0 ) {
+ break;
+ } else {
+ DEBUGC(DBCLASS_DNS, "_resolve: A[%i] - type SRV pr=%i, we=%i, "
+ "po=%i name=[%s]", i, pr, we, po, tmpname);
+ if( !priority || pr < priority ||
+ (pr == priority && we > weight) ) {
+ priority = pr;
+ weight = we;
+ *port = po;
+ strncpy(dname, tmpname, dnamelen);
+/*&&& here the magic with the priorities should go.
+which one do we use? RFC3263 talks a bit on how a stateless
+SIP proxy should handle it - BY GOING STATEFUL if the lowest priority
+is unavailable. Why do I have a stateless proxy? Exactly, because I
+do NOT want to do the whole stateful crap.
+Rethinking needed.
+Currently just the first (lowest prio, highest weight) entry is returned.
+*/
+ xptr+=j;
+ }
+ }
+#if 0
+ } else if( ty == T_NAPTR ) {
DEBUGC(DBCLASS_DNS, "_resolve: A - type NAPTR");
usp = (unsigned short *)xptr;
xptr += sizeof(short);
@@ -171,7 +215,10 @@ static int _resolve(char *name, int proto, int type,
} else {
/*
* there should be some REGEX magic, no?
+ * Not yet used nor implemented. Just complain in
+ * case somebody feels lucky enough trying to use it.
*/
+ERROR("_resolve: NAPTR lookup not yet supported.");
if( proto == PROTO_UDP ) {
if( strstr(tmpname, "_udp" ) ) {
strncpy(dname, tmpname, dnamelen);
@@ -185,34 +232,7 @@ static int _resolve(char *name, int proto, int type,
i, tmpname);
xptr+=j;
}
- } else if( ty == T_SRV ) {
- u_short pr;
- u_short we;
- u_short po;
- usp = (unsigned short *)xptr;
- pr = ntohs( *usp );
- xptr += sizeof( short );
- usp = (unsigned short *)xptr;
- we = ntohs( *usp );
- xptr += sizeof( short );
- usp = (unsigned short *)xptr;
- po = ntohs( *usp );
- xptr += sizeof( short );
- j = dn_expand( msg, msg + PACKETSZ, xptr, tmpname, MAXDNAME );
- if( j < 0 ) {
- break;
- } else {
- DEBUGC(DBCLASS_DNS, "_resolve: A[%i] - type SRV pr=%i, we=%i, "
- "po=%i name=[%s]", i, pr, we, po, tmpname);
- if( !priority || pr < priority ||
- (pr == priority && we < weight) ) {
- priority = pr;
- weight = we;
- *port = po;
- strncpy(dname, tmpname, dnamelen);
- xptr+=j;
- }
- }
+#endif
} else {
ERROR("_resolve: unknown type in DNS answer [type=%i]\n", ty);
} // if ty