- made ipv4<->ipv6 possible ipv6
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Sun, 26 May 2002 21:38:02 +0000 (21:38 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Sun, 26 May 2002 21:38:02 +0000 (21:38 +0000)
- added different port numbers (eg. ser -l foo -p 1234 -l bar -p 4321 )
- small signal fixes (sigterm to evrybody on exit, exit if 1 child dies a.s.o)

15 files changed:
Makefile.defs
action.c
cfg.lex
cfg.y
config.h
forward.c
forward.h
globals.h
ip_addr.h
main.c
msg_translator.c
msg_translator.h
receive.c
udp_server.c
udp_server.h

index e8311e7..e2aed93 100644 (file)
@@ -8,7 +8,7 @@
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL = 8
-EXTRAVERSION = -1-ipv6
+EXTRAVERSION = -2-ipv6
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s)
index 475a2f7..7ef9706 100644 (file)
--- a/action.c
+++ b/action.c
@@ -38,6 +38,7 @@ int do_action(struct action* a, struct sip_msg* msg)
        int ret;
        int v;
        union sockaddr_union* to;
+       struct socket_info* send_sock;
        struct proxy_l* p;
        char* tmp;
        char *new_uri, *end, *crt;
@@ -144,8 +145,13 @@ int do_action(struct action* a, struct sip_msg* msg)
                        if (ret==0){
                                p->tx++;
                                p->tx_bytes+=msg->len;
-                               ret=udp_send(msg->orig, msg->len, to,
-                                                               sizeof(union sockaddr_union));
+                               send_sock=get_send_socket(to);
+                               if (send_sock!=0){
+                                       ret=udp_send(send_sock, msg->orig, msg->len, to,
+                                                                       sizeof(union sockaddr_union));
+                               }else{
+                                       ret=-1;
+                               }
                        }
                        free(to);
                        if (ret<0){
diff --git a/cfg.lex b/cfg.lex
index 0d24ec6..3172ebf 100644 (file)
--- a/cfg.lex
+++ b/cfg.lex
@@ -25,7 +25,7 @@
        
        static int comment_nest=0;
        static int state=0;
-       static char* str=0;
+       static char* tstr=0;
        int line=1;
        int column=1;
        int startcolumn=1;
@@ -219,29 +219,29 @@ EAT_ABLE  [\ \t\b\r]
 
 <STRING1>{QUOTES} { count(); state=INITIAL_S; BEGIN(INITIAL); 
                                                yytext[yyleng-1]=0; yyleng--;
-                                               addstr(yytext, &str);
-                                               yylval.strval=str; str=0;
+                                               addstr(yytext, &tstr);
+                                               yylval.strval=tstr; tstr=0;
                                                return STRING;
                                        }
 <STRING2>{TICK}  { count(); state=INITIAL_S; BEGIN(INITIAL); 
                                                yytext[yyleng-1]=0; yyleng--;
-                                               addstr(yytext, &str);
-                                               yylval.strval=str;
-                                               str=0;
+                                               addstr(yytext, &tstr);
+                                               yylval.strval=tstr;
+                                               tstr=0;
                                                return STRING;
                                        }
 <STRING2>.|{EAT_ABLE}|{CR}     { yymore(); }
 
 <STRING1>\\n           { count(); yytext[yyleng-2]='\n';yytext[yyleng-1]=0; 
-                                               yyleng--; addstr(yytext, &str); }
+                                               yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\r           { count(); yytext[yyleng-2]='\r';yytext[yyleng-1]=0; 
-                                               yyleng--; addstr(yytext, &str); }
+                                               yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\a           { count(); yytext[yyleng-2]='\a';yytext[yyleng-1]=0; 
-                                               yyleng--; addstr(yytext, &str); }
+                                               yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\t           { count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; 
-                                               yyleng--; addstr(yytext, &str); }
+                                               yyleng--; addstr(yytext, &tstr); }
 <STRING1>\\\\          { count(); yytext[yyleng-2]='\\';yytext[yyleng-1]=0; 
-                                               yyleng--; addstr(yytext, &str); } 
+                                               yyleng--; addstr(yytext, &tstr); } 
 <STRING1>.|{EAT_ABLE}|{CR}     { yymore(); }
 
 
@@ -257,8 +257,8 @@ EAT_ABLE    [\ \t\b\r]
 
 <INITIAL>{COM_LINE}.*{CR}      { count(); } 
 
-<INITIAL>{ID}                  { count(); addstr(yytext, &str);
-                                                 yylval.strval=str; str=0; return ID; }
+<INITIAL>{ID}                  { count(); addstr(yytext, &tstr);
+                                                 yylval.strval=tstr; tstr=0; return ID; }
 
 
 <<EOF>>                                                        {
@@ -266,7 +266,7 @@ EAT_ABLE    [\ \t\b\r]
                                                                                case STRING_S: 
                                                                                        LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF in"
                                                                                                                " unclosed string\n");
-                                                                                       if (str) {free(str); str=0;}
+                                                                                       if (tstr) {free(tstr); tstr=0;}
                                                                                        break;
                                                                                case COMMENT_S:
                                                                                        LOG(L_CRIT, "ERROR: cfg. parser: unexpected EOF:"
diff --git a/cfg.y b/cfg.y
index 6b7a2e9..2d65f4d 100644 (file)
--- a/cfg.y
+++ b/cfg.y
@@ -164,7 +164,10 @@ assign_stm:        DEBUG EQUAL NUMBER { debug=$3; }
                | DNS EQUAL error { yyerror("boolean value expected"); }
                | REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
                | REV_DNS EQUAL error { yyerror("boolean value expected"); }
-               | PORT EQUAL NUMBER   { port_no=$3; }
+               | PORT EQUAL NUMBER   { port_no=$3; 
+                                                               if (sock_no>0) 
+                                                                       sock_info[sock_no-1].port_no=port_no;
+                                                         }
                | STAT EQUAL STRING {
                                        #ifdef STATS
                                                        stat_file=$3;
@@ -180,7 +183,7 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; }
                | LOOP_CHECKS EQUAL NUMBER { loop_checks=$3; }
                | LOOP_CHECKS EQUAL error { yyerror("boolean value expected"); }
                | LISTEN EQUAL ip  {
-                                                               if (addresses_no < MAX_LISTEN){
+                                                               if (sock_no< MAX_LISTEN){
                                                                        tmp=ip_addr2a($3);
                                                                /*      tmp=inet_ntoa(*(struct in_addr*)&$3);*/
                                                                        if (tmp==0){
@@ -188,15 +191,19 @@ assign_stm:       DEBUG EQUAL NUMBER { debug=$3; }
                                                                                        " bad ip address: %s\n",
                                                                                        strerror(errno));
                                                                        }else{
-                                                                               names[addresses_no]=
+                                                                               sock_info[sock_no].name.s=
                                                                                                (char*)malloc(strlen(tmp)+1);
-                                                                               if (names[addresses_no]==0){
+                                                                               if (sock_info[sock_no].name.s==0){
                                                                                        LOG(L_CRIT, "ERROR: cfg. parser: "
                                                                                                                "out of memory.\n");
                                                                                }else{
-                                                                                       strncpy(names[addresses_no], tmp,
-                                                                                                       strlen(tmp)+1);
-                                                                                       addresses_no++;
+                                                                                       strncpy(sock_info[sock_no].name.s,
+                                                                                                       tmp, strlen(tmp)+1);
+                                                                                       sock_info[sock_no].name.len=
+                                                                                                       strlen(tmp);
+                                                                                       sock_info[sock_no].port_no=
+                                                                                                       port_no;
+                                                                                       sock_no++;
                                                                                }
                                                                        }
                                                                }else{
@@ -206,16 +213,18 @@ assign_stm:       DEBUG EQUAL NUMBER { debug=$3; }
                                                                }
                                                          }
                | LISTEN EQUAL ID        {
-                                                               if (addresses_no < MAX_LISTEN){
-                                                                       names[addresses_no]=
+                                                               if (sock_no < MAX_LISTEN){
+                                                                       sock_info[sock_no].name.s=
                                                                                                (char*)malloc(strlen($3)+1);
-                                                                       if (names[addresses_no]==0){
+                                                                       if (sock_info[sock_no].name.s==0){
                                                                                LOG(L_CRIT, "ERROR: cfg. parser:"
                                                                                                                " out of memory.\n");
                                                                        }else{
-                                                                               strncpy(names[addresses_no], $3,
+                                                                               strncpy(sock_info[sock_no].name.s, $3,
                                                                                                        strlen($3)+1);
-                                                                               addresses_no++;
+                                                                               sock_info[sock_no].name.len=strlen($3);
+                                                                               sock_info[sock_no].port_no= port_no;
+                                                                               sock_no++;
                                                                        }
                                                                }else{
                                                                        LOG(L_CRIT, "ERROR: cfg. parser: "
@@ -224,16 +233,18 @@ assign_stm:       DEBUG EQUAL NUMBER { debug=$3; }
                                                                }
                                                          }
                | LISTEN EQUAL STRING {
-                                                               if (addresses_no < MAX_LISTEN){
-                                                                       names[addresses_no]=
+                                                               if (sock_no < MAX_LISTEN){
+                                                                       sock_info[sock_no].name.s=
                                                                                (char*)malloc(strlen($3)+1);
-                                                                       if (names[addresses_no]==0){
+                                                                       if (sock_info[sock_no].name.s==0){
                                                                                LOG(L_CRIT, "ERROR: cfg. parser:"
                                                                                                        " out of memory.\n");
                                                                        }else{
-                                                                               strncpy(names[addresses_no], $3,
+                                                                               strncpy(sock_info[sock_no].name.s, $3,
                                                                                                strlen($3)+1);
-                                                                               addresses_no++;
+                                                                               sock_info[sock_no].name.len=strlen($3);
+                                                                               sock_info[sock_no].port_no=port_no;
+                                                                               sock_no++;
                                                                        }
                                                                }else{
                                                                        LOG(L_CRIT, "ERROR: cfg. parser: "
index 003ddb9..29ca595 100644 (file)
--- a/config.h
+++ b/config.h
@@ -64,7 +64,6 @@
 #define SHM_MEM_SIZE 128 
 
 #define TIMER_TICK 1
-#define LONG_SLEEP     3600
 
 /* dimensioning buckets in q_malloc */
 /* size of the size2bucket table; everything beyond that asks for
index 182a5f4..732f5db 100644 (file)
--- a/forward.c
+++ b/forward.c
 
 
 
+/* returns a socket_info pointer to the sending socket or 0 on error
+ * params: destination socke_union pointer
+ */
+struct socket_info* get_send_socket(union sockaddr_union* to)
+{
+       struct socket_info* send_sock;
+       
+       send_sock=0;
+       /* check if we need to change the socket (different address families -
+        * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
+       if (to->s.sa_family!=bind_address->address.af){
+               switch(to->s.sa_family){
+                       case AF_INET:   send_sock=sendipv4;
+                                                       break;
+#ifdef USE_IPV6
+                       case AF_INET6:  send_sock=sendipv6;
+                                                       break;
+#endif
+                       default:                LOG(L_ERR, "get_send_socket: BUG: don't know how"
+                                                                       " to forward to af %d\n", to->s.sa_family);
+               }
+       }else send_sock=bind_address;
+       return send_sock;
+}
+
+
+
 int forward_request( struct sip_msg* msg, struct proxy_l * p)
 {
        unsigned int len;
        char* buf;
        union sockaddr_union* to;
-
+       struct socket_info* send_sock;
+       
        to=0;
-       buf = build_req_buf_from_sip_req( msg, &len);
-       if (!buf){
-               LOG(L_ERR, "ERROR: forward_reply: building failed\n");
-               goto error;
-       }
-
+       buf=0;
+       
        to=(union sockaddr_union*)malloc(sizeof(union sockaddr_union));
        if (to==0){
                LOG(L_ERR, "ERROR: forward_request: out of memory\n");
                goto error;
        }
-
-        /* send it! */
-       DBG("Sending:\n%s.\n", buf);
-       DBG("orig. len=%d, new_len=%d\n", msg->len, len );
-
+       
+       
        /* if error try next ip address if possible */
        if (p->ok==0){
                if (p->host.h_addr_list[p->addr_idx+1])
@@ -64,13 +85,31 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
                else p->addr_idx=0;
                p->ok=1;
        }
-
+       
        hostent2su(to, &p->host, p->addr_idx, 
                                (p->port)?htons(p->port):htons(SIP_PORT));
        p->tx++;
        p->tx_bytes+=len;
+       
 
-       if (udp_send( buf, len,  to, sizeof(union sockaddr_union))==-1){
+       send_sock=get_send_socket(to);
+       if (send_sock==0){
+               LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d "
+                               "no coresponding listening socket\n", to->s.sa_family);
+               goto error;
+       }
+       
+       buf = build_req_buf_from_sip_req( msg, &len, send_sock);
+       if (!buf){
+               LOG(L_ERR, "ERROR: forward_reply: building failed\n");
+               goto error;
+       }
+        /* send it! */
+       DBG("Sending:\n%s.\n", buf);
+       DBG("orig. len=%d, new_len=%d\n", msg->len, len );
+       
+       if (udp_send( send_sock, buf, len,  to, 
+                                                       sizeof(union sockaddr_union))==-1){
                        p->errors++;
                        p->ok=0;
                        STATS_TX_DROPS;
@@ -145,6 +184,7 @@ int forward_reply(struct sip_msg* msg)
        int  r;
        char* new_buf;
        union sockaddr_union* to;
+       struct socket_info* send_sock;
        unsigned int new_len;
        struct sr_module *mod;
        
@@ -152,11 +192,14 @@ int forward_reply(struct sip_msg* msg)
        new_buf=0;
        /*check if first via host = us */
        if (check_via){
-               for (r=0; r<addresses_no; r++)
-                       if(strcmp(msg->via1->host.s, names[r])==0) break;
-               if (r==addresses_no){
+               for (r=0; r<sock_no; r++)
+                       if ( (msg->via1->host.len==sock_info[r].name.len) && 
+                                       (memcmp(msg->via1->host.s, sock_info[r].name.s, 
+                                                                               sock_info[r].name.len)==0) )
+                               break;
+               if (r==sock_no){
                        LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
-                                       " %s\n", msg->via1->host.s);
+                                       " %.*s\n", msg->via1->host.len, msg->via1->host.s);
                        /* send error msg back? */
                        goto error;
                }
@@ -192,8 +235,13 @@ int forward_reply(struct sip_msg* msg)
        }
 
        if (update_sock_struct_from_via( to, msg->via2 )==-1) goto error;
+       send_sock=get_send_socket(to);
+       if (send_sock==0){
+               LOG(L_ERR, "forward_reply: ERROR: no sending socket found\n");
+               goto error;
+       }
 
-       if (udp_send(new_buf,new_len,  to,
+       if (udp_send(send_sock, new_buf,new_len,  to,
                                sizeof(union sockaddr_union))==-1)
        {
                STATS_TX_DROPS;
index aa7e52d..6bc3f85 100644 (file)
--- a/forward.h
+++ b/forward.h
@@ -9,8 +9,10 @@
 #include "parser/msg_parser.h"
 #include "route.h"
 #include "proxy.h"
+#include "ip_addr.h"
 
 
+struct socket_info* get_send_socket(union sockaddr_union* su);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
 int update_sock_struct_from_via( union sockaddr_union* to,
                                                                struct via_body* via );
index 15056c4..5d3b8ba 100644 (file)
--- a/globals.h
+++ b/globals.h
 
 #include "types.h"
 #include "ip_addr.h"
+#include "str.h"
 
 #define NO_DNS     0
 #define DO_DNS     1
 #define DO_REV_DNS 2
 
 
+
 extern char * cfg_file;
 extern char *stat_file;
+extern struct socket_info sock_info[]; /* all addresses we listen/send from*/
+extern int sock_no; /* number of addresses/open sockets*/
 extern unsigned short port_no;
+/*
 extern char port_no_str[];
 extern int port_no_str_len;
-extern unsigned int maxbuffer;
+*/
+/*
 extern char * names[];
 extern int names_len[];
 extern struct ip_addr addresses[];
 extern int addresses_no;
-extern struct ip_addr* bind_address;
+*/
+extern struct socket_info* bind_address; /* pointer to the crt. proc. listening address */
+extern int bind_idx; /* same as above but index in the bound[] array */
+extern struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
+extern struct socket_info* sendipv6; /* same as above for ipv6 */
+
+extern unsigned int maxbuffer;
 extern int children_no;
 extern int dont_fork;
 extern int check_via;
index d9628c6..41616cb 100644 (file)
--- a/ip_addr.h
+++ b/ip_addr.h
@@ -9,6 +9,7 @@
 #include <string.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include "str.h"
 
 #ifdef USE_IPV6
        #ifdef FreeBSD                  /* freebsd is brain damaged and needs a different
@@ -49,6 +50,15 @@ union sockaddr_union{
 };
 
 
+struct socket_info{
+       int socket;
+       str name; /* name - eg.: foo.bar or 10.0.0.1 */
+       struct ip_addr address; /* ip address */
+       str address_str;        /* ip address converted to string -- optimization*/
+       unsigned short port_no;  /* port number */
+       str port_no_str; /* port number converted to string -- optimization*/
+};
+
 
 
 /* inits an ip_addr with the addr. info from a hostent structure
@@ -215,6 +225,7 @@ static inline char* ip_addr2a(struct ip_addr* ip)
        register unsigned char a,b,c;
 #ifdef USE_IPV6
        register unsigned char d;
+       register unsigned short hex4;
 #endif
        int r;
        #define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
@@ -225,10 +236,11 @@ static inline char* ip_addr2a(struct ip_addr* ip)
        #ifdef USE_IPV6
                case AF_INET6:
                        for(r=0;r<7;r++){
-                               a=ip->u.addr16[r]>>12;
-                               b=(ip->u.addr16[r]>>8)&0xf;
-                               c=(ip->u.addr16[r]>>4)&0xf;
-                               d=ip->u.addr16[r]&0xf;
+                               hex4=ntohs(ip->u.addr16[r]);
+                               a=hex4>>12;
+                               b=(hex4>>8)&0xf;
+                               c=(hex4>>4)&0xf;
+                               d=hex4&0xf;
                                if (a){
                                        buff[offset]=HEXDIG(a);
                                        buff[offset+1]=HEXDIG(b);
@@ -254,10 +266,11 @@ static inline char* ip_addr2a(struct ip_addr* ip)
                                }
                        }
                        /* last int16*/
-                       a=ip->u.addr16[r]>>12;
-                       b=(ip->u.addr16[r]>>8)&0xf;
-                       c=(ip->u.addr16[r]>>4)&0xf;
-                       d=ip->u.addr16[r]&0xf;
+                       hex4=ntohs(ip->u.addr16[r]);
+                       a=hex4>>12;
+                       b=(hex4>>8)&0xf;
+                       c=(hex4>>4)&0xf;
+                       d=hex4&0xf;
                        if (a){
                                buff[offset]=HEXDIG(a);
                                buff[offset+1]=HEXDIG(b);
diff --git a/main.c b/main.c
index d573dd9..f3ca67d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -122,11 +122,13 @@ static char flags[]=
 ;
 
 static char help_msg[]= "\
-Usage: " NAME " -l address [-l address] [options]\n\
+Usage: " NAME " -l address [-p port] [-l address [-p port]...] [options]\n\
 Options:\n\
     -c           Perform loop checks and compute branches\n\
     -f file      Configuration file (default " CFG_FILE ")\n\
     -p port      Listen on the specified port (default: 5060)\n\
+                 applies to the last address in -l and to all \n\
+                 following that do not have a corespponding -p\n\
     -l address   Listen on the specified address (multiple -l mean\n\
                  listening on more addresses). The default behaviour\n\
                  is to listen on the addresses returned by uname(2)\n\
@@ -195,9 +197,6 @@ void receive_stdin_loop()
 /* global vars */
 
 char* cfg_file = 0;
-unsigned short port_no = 0; /* port on which we listen */
-char port_no_str[MAX_PORT_LEN];
-int port_no_str_len=0;
 unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
                                                                                                  not want to exceed durig the
                                                                                                  auto-probing procedure; may 
@@ -217,11 +216,20 @@ char* chroot_dir = 0;
 int uid = 0;
 int gid = 0;
 
+#if 0
 char* names[MAX_LISTEN];              /* our names */
 int names_len[MAX_LISTEN];            /* lengths of the names*/
 struct ip_addr addresses[MAX_LISTEN]; /* our ips */
 int addresses_no=0;                   /* number of names/ips */
-struct ip_addr* bind_address;        /* listen address of the crt. process */
+#endif
+struct socket_info sock_info[MAX_LISTEN]; /* all addresses we listen/send from*/
+int sock_no=0; /* number of addresses/open sockets*/
+struct socket_info* bind_address; /* pointer to the crt. proc. listening address */
+int bind_idx; /* same as above but index in the bound[] array */
+struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
+struct socket_info* sendipv6; /* same as above for ipv6 */
+
+unsigned short port_no=0; /* default port*/
 
 /* ipc related globals */
 int process_no = 0;
@@ -246,7 +254,6 @@ extern int yyparse();
 static int is_main=0; /* flag = is this the  "main" process? */
 
 char* pid_file = 0; /* filename as asked by use */
-char *pid_fn = 0; /* and with port number appended */
 
 /* daemon init, return 0 on success, -1 on error */
 int daemonize(char*  name)
@@ -255,7 +262,6 @@ int daemonize(char*  name)
        pid_t pid;
        int r, p;
 
-       int pid_fn_len;
 
        p=-1;
 
@@ -288,8 +294,7 @@ int daemonize(char*  name)
        if ((pid=fork())<0){
                LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
                goto error;
-       }
-       if (pid!=0){
+       }else if (pid!=0){
                /* parent process => exit*/
                exit(0);
        }
@@ -301,49 +306,34 @@ int daemonize(char*  name)
        if ((pid=fork())<0){
                LOG(L_CRIT, "Cannot  fork:%s\n", strerror(errno));
                goto error;
-       }
-       if (pid!=0){
+       }else if (pid!=0){
                /*parent process => exit */
                exit(0);
        }
 
        /* added by noh: create a pid file for the main process */
        if (pid_file!=0){
-
-               /* added port number; -jiri */
-               pid_fn_len = strlen(pid_file) + 5 /* long port number */ 
-                       + 1 /* dot */ + 1 /* ZT */ ;
-               pid_fn = malloc( pid_fn_len );
-               if (!pid_fn) {
-                       LOG(L_ERR, "ERROR: There is really no memory for ser\n");
-                       goto error;
-               }
-               if (snprintf(pid_fn, pid_fn_len, "%s.%d", pid_file, port_no )==-1) {
-                       LOG(L_ERR, "ERROR: pidfile printig failed -- perhaps too high port?\n");
-                       goto error;
-               }
                
-                       
-               if ((pid_stream=fopen(pid_fn, "r"))!=NULL){
+               if ((pid_stream=fopen(pid_file, "r"))!=NULL){
                        fscanf(pid_stream, "%d", &p);
                        fclose(pid_stream);
                        if (p==-1){
                                LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid"
-                                       " pid number\n", pid_fn);
+                                       " pid number\n", pid_file);
                                goto error;
                        }
                        if (kill((pid_t)p, 0)==0 || errno==EPERM){
                                LOG(L_CRIT, "running process found in the pid file %s\n",
-                                       pid_fn);
+                                       pid_file);
                                goto error;
                        }else{
                                LOG(L_WARN, "pid file contains old pid, replacing pid\n");
                        }
                }
                pid=getpid();
-               if ((pid_stream=fopen(pid_fn, "w"))==NULL){
+               if ((pid_stream=fopen(pid_file, "w"))==NULL){
                        LOG(L_WARN, "unable to create pid file %s: %s\n", 
-                               pid_fn, strerror(errno));
+                               pid_file, strerror(errno));
                        goto error;
                }else{
                        fprintf(pid_stream, "%i\n", (int)pid);
@@ -378,14 +368,19 @@ int main_loop()
 #ifdef STATS
                setstats( 0 );
 #endif
-               /* only one address */
-               if (udp_init(&addresses[0],port_no)==-1) goto error;
+               /* only one address, we ignore all the others */
+               if (udp_init(&sock_info[0])==-1) goto error;
+               bind_address=&sock_info[0];
+               bind_idx=0;
+               if (sock_no>1){
+                       LOG(L_WARN, "WARNING: using only the first listen address (no fork)\n");
+               }
 
                /* we need another process to act as the timer*/
                if (timer_list){
                                process_no++;
                                if ((pid=fork())<0){
-                                       LOG(L_CRIT,  "ERRROR: main_loop: Cannot fork\n");
+                                       LOG(L_CRIT,  "ERROR: main_loop: Cannot fork\n");
                                        goto error;
                                }
                                
@@ -418,17 +413,28 @@ int main_loop()
                
                return udp_rcv_loop();
        }else{
-               for(r=0;r<addresses_no;r++){
+               for(r=0;r<sock_no;r++){
                        /* create the listening socket (for each address)*/
-                       if (udp_init(&addresses[r], port_no)==-1) goto error;
+                       if (udp_init(&sock_info[r])==-1) goto error;
+                       /* get first ipv4/ipv6 socket*/
+                       if ((sendipv4==0)&&(sock_info[r].address.af==AF_INET))
+                               sendipv4=&sock_info[r];
+       #ifdef USE_IPV6
+                       if((sendipv6==0)&&(sock_info[r].address.af==AF_INET6))
+                               sendipv6=&sock_info[r];
+       #endif
+                       /* all procs should have access to all the sockets (for sending)
+                        * so we open all first*/
+               }
+               for(r=0; r<sock_no;r++){
                        for(i=0;i<children_no;i++){
                                if ((pid=fork())<0){
                                        LOG(L_CRIT,  "main_loop: Cannot fork\n");
                                        goto error;
-                               }
-                               if (pid==0){
+                               }else if (pid==0){
                                             /* child */
-
+                                       bind_address=&sock_info[r]; /* shortcut */
+                                       bind_idx=r;
                                        if (init_child(i) < 0) {
                                                LOG(L_ERR, "init_child failed\n");
                                                goto error;
@@ -452,6 +458,9 @@ int main_loop()
        pids[process_no]=getpid();
        process_bit = 0;
        is_main=1;
+       bind_address=&sock_info[0]; /* main proc -> it shoudln't send anything, if it does */
+       bind_idx=0;                                     /*   it will use the first address */
+
        if (timer_list){
                for(;;){
                        /* debug:  instead of doing something usefull */
@@ -461,7 +470,7 @@ int main_loop()
                        timer_ticker();
                }
        }else{
-               for(;;) sleep(LONG_SLEEP);
+               for(;;) pause(); 
        }
        
        /*return 0; */
@@ -474,8 +483,7 @@ int main_loop()
 /* added by jku; allows for regular exit on a specific signal;
    good for profiling which only works if exited regularly and
    not by default signal handlers
-*/     
-
+*/
 static void sig_usr(int signo)
 {
        pid_t   chld;
@@ -508,6 +516,8 @@ static void sig_usr(int signo)
                }
 #endif
                dprint("Thank you for flying " NAME "\n");
+               /* kill children also*/
+               kill(0, SIGTERM);
                exit(0);
        } else if (signo==SIGTERM) { /* exit gracefully as daemon */
                DPrint("TERM received, program terminates\n");
@@ -515,11 +525,11 @@ static void sig_usr(int signo)
 #ifdef STATS
                        dump_all_statistic();
 #endif
-                       if (pid_fn) {
-                               unlink(pid_fn);
-                               free(pid_fn);
+                       if (pid_file) {
+                               unlink(pid_file);
                        }
                }
+               kill(0, SIGTERM);
                exit(0);
        } else if (signo==SIGUSR1) { /* statistic */
 #ifdef STATS
@@ -549,6 +559,9 @@ static void sig_usr(int signo)
                                LOG(L_INFO, "child process %d stopped by a signal %d\n",
                                        chld, WSTOPSIG(chld_status));
                }
+               /* exit */
+               kill(0, SIGTERM);
+               exit(0);
        }
 }
 
@@ -564,6 +577,8 @@ int main(int argc, char** argv)
        char *tmp;
        struct utsname myname;
        char *options;
+       char port_no_str[MAX_PORT_LEN];
+       int port_no_str_len=0;
 
        /* added by jku: add exit handler */
        if (signal(SIGINT, sig_usr) == SIG_ERR ) {
@@ -589,9 +604,6 @@ int main(int argc, char** argv)
                goto error;
        }
 
-       //memtest();
-       //hashtest();
-
        /* process command line (get port no, cfg. file path etc) */
        opterr=0;
        options=
@@ -616,34 +628,43 @@ int main(int argc, char** argv)
                                                fprintf(stderr, "bad port number: -p %s\n", optarg);
                                                goto error;
                                        }
+                                       if (sock_no>0) sock_info[sock_no-1].port_no=port_no;
                                        break;
 
                        case 'm':
                                        shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
                                        if (tmp &&(*tmp)){
-                                               fprintf(stderr, "bad shmem size number: -m %s\n", optarg);
+                                               fprintf(stderr, "bad shmem size number: -m %s\n",
+                                                                               optarg);
                                                goto error;
                                        };
-                                       LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", shm_mem_size );
+                                       LOG(L_INFO, "ser: shared memory allocated: %d MByte\n",
+                                                                       shm_mem_size );
                                        break;
 
                        case 'b':
                                        maxbuffer=strtol(optarg, &tmp, 10);
                                        if (tmp &&(*tmp)){
-                                                fprintf(stderr, "bad max buffer size number: -p %s\n", optarg);
-                                                goto error;
-                                        }
-                                        break;
+                                               fprintf(stderr, "bad max buffer size number: -p %s\n",
+                                                                                       optarg);
+                                               goto error;
+                                       }
+                                       break;
                        case 'l':
                                        /* add a new addr. to our address list */
-                                       if (addresses_no < MAX_LISTEN){
-                                               names[addresses_no]=(char*)malloc(strlen(optarg)+1);
-                                               if (names[addresses_no]==0){
+                                       if (sock_no < MAX_LISTEN){
+                                               sock_info[sock_no].name.s=
+                                                                               (char*)malloc(strlen(optarg)+1);
+                                               if (sock_info[sock_no].name.s==0){
                                                        fprintf(stderr, "Out of memory.\n");
                                                        goto error;
                                                }
-                                               strncpy(names[addresses_no], optarg, strlen(optarg)+1);
-                                               addresses_no++;
+                                               strncpy(sock_info[sock_no].name.s, optarg,
+                                                                                               strlen(optarg)+1);
+                                               sock_info[sock_no].name.len=strlen(optarg);
+                                               /* set default port */
+                                               sock_info[sock_no].port_no=port_no;
+                                               sock_no++;
                                        }else{
                                                fprintf(stderr, 
                                                                        "Too many addresses (max. %d).\n",
@@ -654,7 +675,8 @@ int main(int argc, char** argv)
                        case 'n':
                                        children_no=strtol(optarg, &tmp, 10);
                                        if ((tmp==0) ||(*tmp)){
-                                               fprintf(stderr, "bad process number: -n %s\n", optarg);
+                                               fprintf(stderr, "bad process number: -n %s\n",
+                                                                       optarg);
                                                goto error;
                                        }
                                        break;
@@ -784,16 +806,6 @@ int main(int argc, char** argv)
 
        /* fix parameters */
        if (port_no<=0) port_no=SIP_PORT;
-       port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
-                               (unsigned short) port_no);
-       if (port_no_str_len<0){
-               fprintf(stderr, "ERROR: bad port number: %d\n", port_no);
-               goto error;
-       }
-       /* on some system snprintf return really strange things if it does not 
-          have  enough space */
-       port_no_str_len=
-                               (port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
 
        
        if (children_no<=0) children_no=CHILD_NO;
@@ -817,42 +829,63 @@ int main(int argc, char** argv)
        }
        memset(pids, 0, sizeof(int)*(children_no+1));
 
-       if (addresses_no==0) {
+       if (sock_no==0) {
                /* get our address, only the first one */
                if (uname (&myname) <0){
                        fprintf(stderr, "cannot determine hostname, try -l address\n");
                        goto error;
                }
-               names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1);
-               if (names[addresses_no]==0){
+               sock_info[sock_no].name.s=(char*)malloc(strlen(myname.nodename)+1);
+               if (sock_info[sock_no].name.s==0){
                        fprintf(stderr, "Out of memory.\n");
                        goto error;
                }
-               strncpy(names[addresses_no], myname.nodename,
+               strncpy(sock_info[sock_no].name.s, myname.nodename,
                                strlen(myname.nodename)+1);
-               addresses_no++;
+               sock_info[sock_no].name.len=strlen(myname.nodename);
+               sock_no++;
        }
 
-       /*get name lens*/
-       for(r=0; r<addresses_no; r++){
-               names_len[r]=strlen(names[r]);
-       }
-
-       
-       /* get ips */
+       /* get ips & fill the port numbers*/
        printf("Listening on ");
-       for (r=0; r<addresses_no;r++){
-               he=resolvehost(names[r]);
+       for (r=0; r<sock_no;r++){
+               he=resolvehost(sock_info[r].name.s);
                if (he==0){
-                       DPrint("ERROR: could not resolve %s\n", names[r]);
+                       DPrint("ERROR: could not resolve %s\n", sock_info[r].name.s);
                        goto error;
                }
-               hostent2ip_addr(&addresses[r], he, 0); /*convert to ip_addr format*/
-               /*memcpy(&addresses[r], he->h_addr_list[0], sizeof(int));*/
-               /*addresses[r]=*((long*)he->h_addr_list[0]);*/
-               printf("%s [",names[r]);
-               stdout_print_ip(&addresses[r]);
-               printf("]:%d\n", (unsigned short)port_no);
+               hostent2ip_addr(&sock_info[r].address, he, 0); /*convert to ip_addr format*/
+               tmp=ip_addr2a(&sock_info[r].address);
+               sock_info[r].address_str.s=(char*)malloc(strlen(tmp)+1);
+               if (sock_info[r].address_str.s==0){
+                       fprintf(stderr, "Out of memory.\n");
+                       goto error;
+               }
+               strncpy(sock_info[r].address_str.s, tmp, strlen(tmp)+1);
+               sock_info[r].address_str.len=strlen(tmp);
+               
+               if (sock_info[r].port_no==0) sock_info[r].port_no=port_no;
+               port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
+                                                                       (unsigned short) sock_info[r].port_no);
+               if (port_no_str_len<0){
+                       fprintf(stderr, "ERROR: bad port number: %d\n", 
+                                               sock_info[r].port_no);
+                       goto error;
+               }
+               /* on some system snprintf return really strange things if it does not 
+                       have  enough space */
+               port_no_str_len=
+                               (port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
+               sock_info[r].port_no_str.s=(char*)malloc(strlen(port_no_str)+1);
+               if (sock_info[r].port_no_str.s==0){
+                       fprintf(stderr, "Out of memory.\n");
+                       goto error;
+               }
+               strncpy(sock_info[r].port_no_str.s, port_no_str, strlen(port_no_str)+1);
+               sock_info[r].port_no_str.len=strlen(port_no_str);
+               
+               printf("%s [%s]:%s\n",sock_info[r].name.s, sock_info[r].address_str.s,
+                               sock_info[r].port_no_str.s);
        }
 
 #ifdef STATS
index 36d64d4..c29d858 100644 (file)
@@ -89,30 +89,45 @@ int check_address(struct ip_addr* ip, char *name, int resolver)
 
 
 
-char* via_builder( struct sip_msg *msg , unsigned int *len )
+char* via_builder( struct sip_msg *msg , unsigned int *len, 
+                                       struct socket_info* send_sock )
 {
-       unsigned int  via_len, branch_len;
+       unsigned int  via_len, branch_len, extra_len;;
        char               *line_buf;
 
        line_buf=0;
+       extra_len=0;
 
        line_buf=pkg_malloc(sizeof(char)*MAX_VIA_LINE_SIZE);
        if (line_buf==0){
                LOG(L_ERR, "ERROR: via_builder: out of memory\n");
                goto error;
        }
-       via_len=MY_VIA_LEN+names_len[0]; /* space included in MY_VIA*/
+       via_len=MY_VIA_LEN+send_sock->address_str.len; /*space included in MY_VIA*/
+#ifdef USE_IPV6
+       if (send_sock->address.af==AF_INET6) via_len+=2; /* [ ]*/
+#endif
 
        /* jku: if we compute branches using MD5 it will take 32 bytes */
        branch_len= (loop_checks ? MY_BRANCH_LEN : MY_BRANCH_LEN -1 + MD5_LEN)+
                                        msg->add_to_branch_len;
 
-       if ((via_len+port_no_str_len+branch_len+CRLF_LEN)<MAX_VIA_LINE_SIZE){
+       if ((via_len+send_sock->port_no_str.len+branch_len
+                                                               +CRLF_LEN)<MAX_VIA_LINE_SIZE){
                memcpy(line_buf, MY_VIA, MY_VIA_LEN);
-               memcpy(line_buf+MY_VIA_LEN, names[0], names_len[0]);
-               if (port_no!=SIP_PORT){
-                       memcpy(line_buf+via_len, port_no_str, port_no_str_len);
-                       via_len+=port_no_str_len;
+#ifdef USE_IPV6
+       if (send_sock->address.af==AF_INET6) {
+               line_buf[MY_VIA_LEN]='[';
+               line_buf[MY_VIA_LEN+1+send_sock->address_str.len]=']';
+               extra_len=1;
+       }
+#endif
+               memcpy(line_buf+MY_VIA_LEN+extra_len, send_sock->address_str.s,
+                                                                       send_sock->address_str.len);
+               if (send_sock->port_no!=SIP_PORT){
+                       memcpy(line_buf+via_len, send_sock->port_no_str.s,
+                                                                        send_sock->port_no_str.len);
+                       via_len+=send_sock->port_no_str.len;
                }
 
                /* jku: branch parameter */
@@ -222,7 +237,8 @@ done:
 
 
 char * build_req_buf_from_sip_req( struct sip_msg* msg,
-                                                               unsigned int *returned_len)
+                                                               unsigned int *returned_len,
+                                                               struct socket_info* send_sock)
 {
        unsigned int len, new_len, received_len, uri_len, via_len, extra_len;
        char* line_buf;
@@ -249,7 +265,7 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
        extra_len=0;
 
 
-       line_buf = via_builder( msg, &via_len );
+       line_buf = via_builder( msg, &via_len, send_sock);
        if (!line_buf){
                LOG(L_ERR,"ERROR: build_req_buf_from_sip_req: no via received!\n");
                goto error1;
index 37ebcd2..e942e45 100644 (file)
@@ -9,9 +9,10 @@
 #define MY_HF_SEP_LEN 2
 
 #include "parser/msg_parser.h"
+#include "ip_addr.h"
 
 char * build_req_buf_from_sip_req (    struct sip_msg* msg, 
-                               unsigned int *returned_len);
+                               unsigned int *returned_len, struct socket_info* send_sock);
 
 char * build_res_buf_from_sip_res(     struct sip_msg* msg,
                                unsigned int *returned_len);
@@ -23,7 +24,7 @@ char * build_res_buf_from_sip_req(    unsigned int code ,
                                struct sip_msg* msg,
                                unsigned int *returned_len);
 char* via_builder(                     struct sip_msg *msg ,
-                               unsigned int *len );
+                               unsigned int *len, struct socket_info* send_sock);
 
 
 #endif
index 5b1af6b..e1fff4b 100644 (file)
--- a/receive.c
+++ b/receive.c
@@ -43,7 +43,7 @@ int receive_msg(char* buf, unsigned int len, union sockaddr_union* src_su)
        msg->buf=buf;
        msg->len=len;
        su2ip_addr(&msg->src_ip, src_su);
-       msg->dst_ip=*bind_address; /* won't work if listening on 0.0.0.0 */
+       msg->dst_ip=bind_address->address; /* won't work if listening on 0.0.0.0 */
        msg->id=msg_no;
        /* make a copy of the message */
        msg->orig=(char*) pkg_malloc(len+1);
index fd8e60f..5f4ac67 100644 (file)
@@ -23,7 +23,6 @@
 #include <mem/dmalloc.h>
 #endif
 
-int udp_sock;
 
 int probe_max_receive_buffer( int udp_sock )
 {
@@ -107,7 +106,7 @@ int probe_max_receive_buffer( int udp_sock )
        /* EoJKU */
 }
 
-int udp_init(struct ip_addr* ip, unsigned short port)
+int udp_init(struct socket_info* sock_info)
 {
        union sockaddr_union* addr;
        int optval;
@@ -119,7 +118,7 @@ int udp_init(struct ip_addr* ip, unsigned short port)
                goto error;
        }
        
-       if (init_su(addr, ip, htons(port))<0){
+       if (init_su(addr, &sock_info->address, htons(sock_info->port_no))<0){
                LOG(L_ERR, "ERROR: udp_init: could not init sockaddr_union\n");
                goto error;
        }
@@ -130,25 +129,33 @@ int udp_init(struct ip_addr* ip, unsigned short port)
        */
 
        
-       udp_sock = socket(AF2PF(addr->s.sa_family), SOCK_DGRAM, 0);
-       if (udp_sock==-1){
+       sock_info->socket = socket(AF2PF(addr->s.sa_family), SOCK_DGRAM, 0);
+       if (sock_info->socket==-1){
                LOG(L_ERR, "ERROR: udp_init: socket: %s\n", strerror(errno));
                goto error;
        }
        /* set sock opts? */
        optval=1;
-       if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR ,
+       if (setsockopt(sock_info->socket, SOL_SOCKET, SO_REUSEADDR ,
                                        (void*)&optval, sizeof(optval)) ==-1)
        {
                LOG(L_ERR, "ERROR: udp_init: setsockopt: %s\n", strerror(errno));
                goto error;
        }
 
-       if ( probe_max_receive_buffer(udp_sock)==-1) goto error;
-       bind_address=ip;
-
-       if (bind(udp_sock,  &addr->s, sizeof(union sockaddr_union))==-1){
-               LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno));
+       if ( probe_max_receive_buffer(sock_info->socket)==-1) goto error;
+
+       if (bind(sock_info->socket,  &addr->s, sizeof(union sockaddr_union))==-1){
+               LOG(L_ERR, "ERROR: udp_init: bind(%x, %p, %d) on %s: %s\n",
+                               sock_info->socket, &addr->s, 
+                               sizeof(union sockaddr_union),
+                               sock_info->address_str.s,
+                               strerror(errno));
+       #ifdef USE_IPV6
+               if (addr->s.sa_family==AF_INET6)
+                       LOG(L_ERR, "ERROR: udp_init: might be caused by using a link "
+                                       " local address, try site local or global\n");
+       #endif
                goto error;
        }
 
@@ -191,8 +198,8 @@ int udp_rcv_loop()
                }
 #endif
                fromlen=sizeof(union sockaddr_union);
-               len=recvfrom(udp_sock, buf, BUF_SIZE, 0, &from->s,
-                                               &fromlen);
+               len=recvfrom(bind_address->socket, buf, BUF_SIZE, 0, &from->s,
+                                                                                       &fromlen);
                if (len==-1){
                        LOG(L_ERR, "ERROR: udp_rcv_loop:recvfrom:[%d] %s\n",
                                                errno, strerror(errno));
@@ -222,15 +229,15 @@ error:
 
 
 /* which socket to use? main socket or new one? */
-int udp_send(char *buf, unsigned len, union sockaddr_union*  to,
-                               unsigned tolen)
+int udp_send(struct socket_info *source, char *buf, unsigned len,
+                               union sockaddr_union*  to, unsigned tolen)
 {
 
        int n;
 
 
 again:
-       n=sendto(udp_sock, buf, len, 0, &to->s, tolen);
+       n=sendto(source->socket, buf, len, 0, &to->s, tolen);
        if (n==-1){
                LOG(L_ERR, "ERROR: udp_send: sendto(sock,%p,%d,0,%p,%d): %s(%d)\n",
                                buf,len,to,tolen,
index 109b1a0..d4acc61 100644 (file)
 #define MAX_RECV_BUFFER_SIZE   256*1024
 #define BUFFER_INCREMENT       2048
 
-extern int udp_sock;
 
-int udp_init(struct ip_addr* ip, unsigned short port);
-int udp_send(char *buf, unsigned len, union sockaddr_union*  to,
-                               unsigned tolen);
+int udp_init(struct socket_info* si);
+int udp_send(struct socket_info* source,char *buf, unsigned len,
+                               union sockaddr_union*  to, unsigned tolen);
 int udp_rcv_loop();