determination of outbound interace introduced (get_out_socket)
authorJiri Kuthan <jiri@iptel.org>
Thu, 23 Jan 2003 12:27:50 +0000 (12:27 +0000)
committerJiri Kuthan <jiri@iptel.org>
Thu, 23 Jan 2003 12:27:50 +0000 (12:27 +0000)
cfg.lex
cfg.y
doc/seruser/seruser.sgml
examples/web_im/send_im.php
forward.c
forward.h
globals.h
main.c

diff --git a/cfg.lex b/cfg.lex
index 0145975..3599558 100644 (file)
--- a/cfg.lex
+++ b/cfg.lex
@@ -2,6 +2,33 @@
  * $Id$
  *
  * scanner for cfg files
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info@iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * -------
+ * 2001-01-23 mhomed added (jiri)
  */
 
 
@@ -111,6 +138,7 @@ SERVER_SIGNATURE server_signature
 REPLY_TO_VIA reply_to_via
 USER           "user"|"uid"
 GROUP          "group"|"gid"
+MHOMED         mhomed
 
 LOADMODULE     loadmodule
 MODPARAM        modparam
@@ -210,6 +238,7 @@ EAT_ABLE    [\ \t\b\r]
 <INITIAL>{SIP_WARNING} { count(); yylval.strval=yytext; return SIP_WARNING; }
 <INITIAL>{USER}                { count(); yylval.strval=yytext; return USER; }
 <INITIAL>{GROUP}       { count(); yylval.strval=yytext; return GROUP; }
+<INITIAL>{MHOMED}      { count(); yylval.strval=yytext; return MHOMED; }
 <INITIAL>{FIFO}        { count(); yylval.strval=yytext; return FIFO; }
 <INITIAL>{FIFO_MODE}   { count(); yylval.strval=yytext; return FIFO_MODE; }
 <INITIAL>{SERVER_SIGNATURE}    { count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
diff --git a/cfg.y b/cfg.y
index 098d405..b6871dc 100644 (file)
--- a/cfg.y
+++ b/cfg.y
@@ -2,6 +2,35 @@
  * $Id$
  *
  *  cfg grammar
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info@iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * ---------
+ * 2003-01-23 mhomed added (jiri)
+ */
+
  */
 
 %{
@@ -122,6 +151,7 @@ struct id_list* lst_tmp;
 %token MAXBUFFER
 %token USER
 %token GROUP
+%token MHOMED
 
 
 
@@ -288,6 +318,8 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; }
                | GROUP EQUAL STRING     { group=$3; }
                | GROUP EQUAL ID         { group=$3; }
                | GROUP EQUAL error      { yyerror("string value expected"); }
+               | MHOMED EQUAL NUMBER { mhomed=$3; }
+               | MHOMED EQUAL error { yyerror("boolean value expected"); }
                | SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
                | SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
                | REPLY_TO_VIA EQUAL NUMBER { reply_to_via=$3; }
index 3a8e09b..4994dd6 100644 (file)
@@ -3137,6 +3137,28 @@ if (to me):
                        </para>
                    </answer>
                </qandaentry>
+               <qandaentry>
+                   <question>
+                       <para>
+                           On a multihomed host, forwarded messages carry other 
+                           interface in Via than used for sending, or messages 
+                           are not sent and an error log is issued "invalid 
+                           sendtoparameters one possible reason is the server 
+                           is bound to localhost".
+                       </para>
+                   </question>
+                   <answer>
+                       <anchor id="mhomed">
+                       <para>
+                           Set the configuration option <varname>mhome</varname>
+                           to "1". <application moreinfo="none">ser</application>
+                           will then attempt to calculate the correct interface.
+                           It's not done by default as it degrades performance
+                           on single-homed hosts or multi-homed hosts that are
+                           not set-up as routers.
+                       </para>
+                   </answer>
+               </qandaentry>
                <qandaentry>
                    <question>
                        <para>
@@ -3530,7 +3552,7 @@ SIP_HF_CONTACT=<sip:123.20.128.35:9315>
                to <filename moreinfo="none">/tmp/</filename> path), to which
                a reply should be printed. The first request line may be
                followed by additional lines with command-specific 
-               parameters. For example, the <command moreinfo="none">t_uac</command>
+               parameters. For example, the <command moreinfo="none">t_uac_dlg</command>
                FIFO command for initiating a transaction allows 
                to pass additional header fields and message body to
                a newly created transaction. Each request is terminated by
@@ -3632,7 +3654,7 @@ print
                (instant message)
                from a PHP script via the FIFO server. This example
                uses FIFO command 
-               <command moreinfo="none">t_uac</command>. The command
+               <command moreinfo="none">t_uac_dlg</command>. The command
                is followed by parameters: header fields and 
                message body. The same FIFO command can be used from
                other environments to send instant messages too. The
@@ -3646,18 +3668,24 @@ print
 # call this script to send an instant message; script parameters
 # will be displayed in message body
 #
+# paremeters mean: message type, request-URI, outbound server is
+# left blank ("."), required header fields From and To follow,
+# then optional header fields terminated by dot and optional
+# dot-terminated body
 
 cat &gt; /tmp/ser_fifo &lt;&lt;EOF
-:t_uac_from:hh
+:t_uac_dlg:hh
 NOTIFY
-sip:originator@foo.bar
 sip:receiver@127.0.0.1
+.
+From: sip:originator@foo.bar
+To: sip:receiver@127.0.0.1
 foo: bar_special_header
 x: y
 p_header: p_value
 Contact: &lt;sip:devnull@192.168.0.100:9&gt;
 Content-Type: text/plain; charset=UTF-8
-
+.
 Hello world!!!! $@
 .
 EOF
@@ -4053,8 +4081,11 @@ Domain Registered Expired
                </listitem>
                <listitem>
                    <para>
-                       <varname>reply_to_via</varname> - A hint to reply modules whether they should send reply
-                       to IP advertised in Via or IP from which a request came.
+                       <varname>reply_to_via</varname> - A hint to reply modules
+                       whether they should send reply
+                       to IP advertised in Via.
+                       Turned off by default, which means that replies are
+                       sent to IP address from which requests came from. 
                    </para>
                </listitem>
                <listitem>
@@ -4067,6 +4098,13 @@ Domain Registered Expired
                        <varname>group | gid</varname> - gid to be used by the server.
                    </para>
                </listitem>
+               <listitem>
+                   <para>
+                       <varname>mhomed</varname> -- enable calculation of 
+                       outbound interface; useful on multihomed servers,
+                       ser <link linkend="mhomed"></link>.
+                   </para>
+               </listitem>
                <listitem>
                    <para>
                        <varname>loadmodule</varname> - Specifies a module to be loaded (for example "/usr/lib/ser/modules/tm.so")
@@ -5094,12 +5132,19 @@ if (len_gt(1024)) {
                            <entry>print occupation of transaction table (mainly for debugging)</entry>
                        </row>
                        <row>
-                           <entry>t_uac_from</entry>
+                           <entry>t_uac_dlg</entry>
                            <entry>tm</entry>
-                           <entry>method, sender's URI, destination URI, optional header fields
-                           terminated by empty line, message body terminated by a line with
-                           a single dot</entry>
-                           <entry>initiate a transaction</entry>
+                           <entry>method, request URI, outbound URI (if none, empty line with a single dot),
+                                       dot-line-terminated header fields, optionaly dot-line terminated message
+                                       body. 
+                               </entry>
+                                       
+                           <entry>initiate a transaction.
+                                       From and To header fields must be present in header field list,
+                                       so does Content-Type if body is present. If CSeq, CallId and From-tag
+                                       are not present, ephemeral values are generated. Content_length is
+                                       calculated automatically if body present.
+                               </entry>
                        </row>
                        <row>
                            <entry>ul_stats</entry>
index 760640d..7c5cabe 100644 (file)
@@ -31,12 +31,14 @@ if (!$fifo_handle) {
 }
 
 /* construct FIFO command */
-$fifo_cmd=":t_uac:".$myfilename."\n".
-    "MESSAGE\n".$sip_address."\n".
+$fifo_cmd=":t_uac_dlg:".$myfilename."\n".
+    "MESSAGE\n".$sip_address."\n.\n".
+       "From: sip:sender@foo.bar\n".
+       "To: ".$sip_address."\n".
     "p-version: ".$signature."\n".
     "Contact: ".$web_contact."\n".
-    "Content-Type: text/plain; charset=UTF-8\n\n".
-    $instant_message."\n.\n\n";
+    "Content-Type: text/plain; charset=UTF-8\n.\n".
+    $instant_message."\n.\n";
 
 /* create fifo for replies */
 system("mkfifo -m 666 ".$mypath );
index 1fcae2e..ef91121 100644 (file)
--- a/forward.c
+++ b/forward.c
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * -------
+ * 2001-01-23 support for determination of outbound interface added :
+ *            get_out_socket (jiri)
+ *
  */
 
 
 #include <dmalloc.h>
 #endif
 
+/* return a socket_info_pointer to the sending socket; as opposed to
+ * get_send_socket, which returns process's default socket, get_out_socket
+ * attempts to determine the outbound interface which will be used;
+ * it creates a temporary connected socket to determine it; it will
+ * be very likely noticeably slower, but it can deal better with
+ * multihomed hosts
+ */
+struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
+{
+       int temp_sock;
+       socklen_t len;
+       int r;
+       union sockaddr_union from; 
+
+       if (proto!=PROTO_UDP) {
+               LOG(L_CRIT, "BUG: get_out_socket can only be called for UDP\n");
+               return 0;
+       }
+
+       r=-1;
+       temp_sock=socket(to->s.sa_family, SOCK_DGRAM, 0 );
+       if (temp_sock==-1) {
+               LOG(L_ERR, "ERROR: get_out_socket: socket() failed: %s\n",
+                               strerror(errno));
+               return 0;
+       }
+       if (connect(temp_sock, &to->s, sockaddru_len(*to))==-1) {
+               LOG(L_ERR, "ERROR: get_out_socket: connect failed: %s\n",
+                               strerror(errno));
+               goto error;
+       }
+       len=sockaddru_len(from);
+       if (getsockname(temp_sock, &from.s, &len)==-1) {
+               LOG(L_ERR, "ERROR: get_out_socket: getsockname failed: %s\n",
+                               strerror(errno));
+               goto error;
+       }
+       for (r=0; r<sock_no; r++) {
+               switch(from.s.sa_family) {
+                       case AF_INET:   
+                                               if (sock_info[r].address.af!=AF_INET)
+                                                               continue;
+                                               if (memcmp(&sock_info[r].address.u,
+                                                               &from.sin.sin_addr, 
+                                                               sock_info[r].address.len)==0)
+                                                       goto error; /* it is actually success */
+                                               break;
+                       case AF_INET6:  
+                                               if (sock_info[r].address.af!=AF_INET6)
+                                                               continue;
+                                               if (memcmp(&sock_info[r].address.u,
+                                                               &from.sin6.sin6_addr, len)==0)
+                                                       goto error;
+                                               continue;
+                       default:        LOG(L_ERR, "ERROR: get_out_socket: "
+                                                                       "unknown family: %d\n",
+                                                                       from.s.sa_family);
+                                               r=-1;
+                                               goto error;
+               }
+       }
+       LOG(L_ERR, "ERROR: get_out_socket: no socket found\n");
+       r=-1;
+error:
+       close(temp_sock);
+       DBG("DEBUG: get_out_socket: socket determined: %d\n", r );
+       return r==-1? 0: &sock_info[r];
+}
+
 
 
 /* returns a socket_info pointer to the sending socket or 0 on error
 struct socket_info* get_send_socket(union sockaddr_union* to, int proto)
 {
        struct socket_info* send_sock;
-       
+
+       if (mhomed && proto==PROTO_UDP) return get_out_socket(to, proto);
+
        send_sock=0;
        /* check if we need to change the socket (different address families -
         * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
index 711d51b..44d23ef 100644 (file)
--- a/forward.h
+++ b/forward.h
@@ -37,6 +37,7 @@
 
 
 struct socket_info* get_send_socket(union sockaddr_union* su, int proto);
+struct socket_info* get_out_socket(union sockaddr_union* to, int proto);
 int check_self(str* host, unsigned short port);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p, int proto);
 int update_sock_struct_from_via( union sockaddr_union* to,
index 2e5a1ed..748aace 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -113,4 +113,7 @@ extern int is_main;
 /* debugging level for dumping memory status */
 extern int memlog;
 
+/* looking up outbound interface ? */
+extern int mhomed;
+
 #endif
diff --git a/main.c b/main.c
index 8f40a2e..076bb39 100644 (file)
--- a/main.c
+++ b/main.c
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * -------
+ * 2001-01-23 mhomed added (jiri)
+ *
  */
 
 
@@ -263,6 +268,10 @@ int sip_warning = 1;
    be default yes, good for trouble-shooting
 */
 int server_signature=1;
+/* should ser try to locate outbound interface on multihomed
+ * host? by default not -- too expensive
+ */
+int mhomed=0;
 /* use dns and/or rdns or to see if we need to add 
    a ;received=x.x.x.x to via: */
 int received_dns = 0;