- fixed a memroy leak (rewritehost/uri/etc.) sip_083
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 26 Oct 2001 20:28:55 +0000 (20:28 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 26 Oct 2001 20:28:55 +0000 (20:28 +0000)
- added forward to uri support (forward(uri:host, uri:port) ).
- improved free_lump_list speed (could be dangerous)

15 files changed:
README
action.c
cfg.lex
cfg.y
data_lump.c
forward.c
main.c
msg_parser.c
msg_parser.h
proxy.c
proxy.h
route.c
route_struct.h
test/req2.sip [new file with mode: 0644]
test/test3.cfg [new file with mode: 0644]

diff --git a/README b/README
index 39a2124..04ee727 100644 (file)
--- a/README
+++ b/README
@@ -24,6 +24,7 @@ Configuration files:
                - fork
                - children_no
                - log_stderror
+               - loadmodule "path/modulename"
                ...
 
        Logical expressions [missing]
@@ -51,6 +52,10 @@ Configuration files:
                - log
                - exec
                - route/goto
-               - drop
+               - drop/break
+               - if {} else{}
+       Modules:
+               - loadmodule "..."
+               - commands registered by modules
 
 
index 76b2d83..716179c 100644 (file)
--- a/action.c
+++ b/action.c
@@ -41,6 +41,7 @@ int do_action(struct action* a, struct sip_msg* msg)
        int len;
        int user;
        struct sip_uri uri;
+       unsigned short port;
 
        ret=E_BUG;
        switch (a->type){
@@ -48,14 +49,54 @@ int do_action(struct action* a, struct sip_msg* msg)
                                ret=0;
                        break;
                case FORWARD_T:
-                       if ((a->p1_type!= PROXY_ST)|(a->p2_type!=NUMBER_ST)){
+                       if (a->p1_type==URIHOST_ST){
+                               /*parse uri*/
+                               tmp=(msg->new_uri)?msg->new_uri:
+                                               msg->first_line.u.request.uri;
+                               if (parse_uri(tmp, strlen(tmp), &uri)<0){
+                                       LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>,"
+                                                               " dropping packet\n",tmp);
+                                       ret=E_UNSPEC;
+                                       break;
+                               }
+                               switch (a->p2_type){
+                                       case URIPORT_ST:
+                                                                       if (uri.port){
+                                                                               port=strtol(uri.port,&end,10);
+                                                                               if ((end)&&(*end)){
+                                                                                       LOG(L_ERR, "ERROR: do_action: "
+                                                                                                       "forward: bad port in "
+                                                                                                       "uri: <%s>\n", uri.port);
+                                                                                       ret=E_UNSPEC;
+                                                                                       free_uri(&uri);
+                                                                                       goto skip;
+                                                                               }
+                                                                       }else port=SIP_PORT;
+                                                                       break;
+                                       case NUMBER_ST:
+                                                                       port=a->p2.number;
+                                                                       break;
+                                       default:
+                                                       LOG(L_CRIT, "BUG: do_action bad forward 2nd"
+                                                                               " param type (%d)\n", a->p2_type);
+                                                       free_uri(&uri);
+                                                       goto skip;
+                               }
+                               /* create a temporary proxy*/
+                               p=mk_proxy(uri.host, port);
+                               ret=forward_request(msg, p);
+                               free_uri(&uri);
+                               free_proxy(p); /* frees only p content, not p itself */
+                               free(p);
+                               if (ret>=0) ret=1;
+                       }else if ((a->p1_type==PROXY_ST) && (a->p2_type==NUMBER_ST)){
+                               ret=forward_request(msg,(struct proxy_l*)a->p1.data);
+                               if (ret>=0) ret=1;
+                       }else{
                                LOG(L_CRIT, "BUG: do_action: bad forward() types %d, %d\n",
                                                a->p1_type, a->p2_type);
                                ret=E_BUG;
-                               break;
                        }
-                       ret=forward_request(msg, (struct proxy_l*)a->p1.data);
-                       if (ret>=0) ret=1;
                        break;
                case SEND_T:
                        to=(struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
@@ -79,6 +120,8 @@ int do_action(struct action* a, struct sip_msg* msg)
                        if (p->ok==0){
                                if (p->host.h_addr_list[p->addr_idx+1])
                                        p->addr_idx++;
+                               else 
+                                       p->addr_idx=0;
                                p->ok=1;
                        }
                        to->sin_addr.s_addr=*((long*)p->host.h_addr_list[p->addr_idx]);
@@ -186,6 +229,7 @@ int do_action(struct action* a, struct sip_msg* msg)
                                        LOG(L_ERR, "ERROR: do_action: memory allocation "
                                                                " failure\n");
                                        ret=E_OUT_OF_MEM;
+                                       free_uri(&uri);
                                        break;
                                }
                                end=new_uri+MAX_URI_SIZE;
@@ -255,6 +299,7 @@ int do_action(struct action* a, struct sip_msg* msg)
                                /* copy it to the msg */
                                if (msg->new_uri) free(msg->new_uri);
                                msg->new_uri=new_uri;
+                               free_uri(&uri);
                                ret=1;
                                break;
                case IF_T:
@@ -287,10 +332,12 @@ int do_action(struct action* a, struct sip_msg* msg)
                default:
                        LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
        }
+skip:
        return ret;
        
 error_uri:
        LOG(L_ERR, "ERROR: do_action: set*: uri too long\n");
+       free_uri(&uri);
        if (new_uri) free(new_uri);
        return E_UNSPEC;
 }
@@ -321,7 +368,8 @@ int run_actions(struct action* a, struct sip_msg* msg)
        for (t=a; t!=0; t=t->next){
                ret=do_action(t, msg);
                if(ret==0) break;
-               else if (ret<0){ ret=-1; goto error; }
+               /* ignore errors */
+               /*else if (ret<0){ ret=-1; goto error; }*/
        }
        
        rec_lev--;
diff --git a/cfg.lex b/cfg.lex
index 2b16b4d..a6221e1 100644 (file)
--- a/cfg.lex
+++ b/cfg.lex
@@ -55,6 +55,10 @@ SET_URI                      "rewriteuri"|"seturi"
 IF                             "if"
 ELSE                   "else"
 
+/*ACTION LVALUES*/
+URIHOST                        "uri:host"
+URIPORT                        "uri:port"
+
 
 /* condition keywords */
 METHOD method
@@ -134,6 +138,9 @@ EAT_ABLE    [\ \t\b\r]
 <INITIAL>{IF}  { count(); yylval.strval=yytext; return IF; }
 <INITIAL>{ELSE}        { count(); yylval.strval=yytext; return ELSE; }
 
+<INITIAL>{URIHOST}     { count(); yylval.strval=yytext; return URIHOST; }
+<INITIAL>{URIPORT}     { count(); yylval.strval=yytext; return URIPORT; }
+
 <INITIAL>{METHOD}      { count(); yylval.strval=yytext; return METHOD; }
 <INITIAL>{URI} { count(); yylval.strval=yytext; return URI; }
 <INITIAL>{SRCIP}       { count(); yylval.strval=yytext; return SRCIP; }
@@ -199,7 +206,7 @@ EAT_ABLE    [\ \t\b\r]
                                                yyleng--; addstr(yytext, &str); }
 <STRING1>\\r           { count(); yytext[yyleng-2]='\r';yytext[yyleng-1]=0; 
                                                yyleng--; addstr(yytext, &str); }
-<STRING1>\\g           { count(); yytext[yyleng-2]='\g';yytext[yyleng-1]=0; 
+<STRING1>\\a           { count(); yytext[yyleng-2]='\a';yytext[yyleng-1]=0; 
                                                yyleng--; addstr(yytext, &str); }
 <STRING1>\\t           { count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; 
                                                yyleng--; addstr(yytext, &str); }
diff --git a/cfg.y b/cfg.y
index a69fbec..db9b9cd 100644 (file)
--- a/cfg.y
+++ b/cfg.y
@@ -57,6 +57,8 @@ void* f_tmp;
 %token SET_URI
 %token IF
 %token ELSE
+%token URIHOST
+%token URIPORT
 
 %token METHOD
 %token URI
@@ -449,6 +451,29 @@ cmd:               FORWARD LPAREN host RPAREN      { $$=mk_action( FORWARD_T,
                                                                                                                                 (void*)$3,
                                                                                                                                (void*)$5);
                                                                                                  }
+               | FORWARD LPAREN URIHOST COMMA URIPORT RPAREN {
+                                                                                                       $$=mk_action(FORWARD_T,
+                                                                                                                                URIHOST_ST,
+                                                                                                                                URIPORT_ST,
+                                                                                                                               0,
+                                                                                                                               0);
+                                                                                                       }
+                                                                                                       
+                                                                       
+               | FORWARD LPAREN URIHOST COMMA NUMBER RPAREN {
+                                                                                                       $$=mk_action(FORWARD_T,
+                                                                                                                                URIHOST_ST,
+                                                                                                                                NUMBER_ST,
+                                                                                                                               0,
+                                                                                                                               (void*)$5);
+                                                                                                       }
+               | FORWARD LPAREN URIHOST RPAREN {
+                                                                                                       $$=mk_action(FORWARD_T,
+                                                                                                                                URIHOST_ST,
+                                                                                                                                NUMBER_ST,
+                                                                                                                               0,
+                                                                                                                               0);
+                                                                               }
                | FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
                | FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
                                                                                "argument"); }
index c736624..1ebbd26 100644 (file)
@@ -186,14 +186,30 @@ void free_lump(struct lump* lmp)
 
 void free_lump_list(struct lump* l)
 {
-       struct lump* t, *crt;
+       struct lump* t, *r, *foo,*crt;
        t=l;
        while(t){
                crt=t;
                t=t->next;
-               /* dangerous recursive clean*/
+       /*
+                dangerous recursive clean
                if (crt->before) free_lump_list(crt->before);
                if (crt->after)  free_lump_list(crt->after);
+       */
+               /* no more recursion, clean after and before and that's it */
+               r=crt->before;
+               while(r){
+                       foo=r; r=r->before;
+                       free_lump(foo);
+                       free(foo);
+               }
+               r=crt->after;
+               while(r){
+                       foo=r; r=r->after;
+                       free_lump(foo);
+                       free(foo);
+               }
+               
                /*clean current elem*/
                free_lump(crt);
                free(crt);
index 2eb3f48..7285673 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -142,8 +142,6 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        new_len=len;
        s_offset=0;
        for(t=msg->add_rm;t;t=t->next){
-               DBG("t=%x, op=%d, offset=%x, len=%d, s_offset=%x\n",
-                               t, t->op, t->u.offset, t->len, s_offset);
                for(r=t->before;r;r=r->before){
                        switch(r->op){
                                case LUMP_ADD:
@@ -162,14 +160,11 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
                        case LUMP_DEL:
                                /* fix overlapping deleted zones */
                                if (t->u.offset < s_offset){
-                                       DBG( "overlapping DEL offsets (%d,%d(%d)), fixing...\n",
-                                                s_offset, t->u.offset, t->len);
                                        /* change len */
                                        if (t->len>s_offset-t->u.offset) 
                                                        t->len-=s_offset-t->u.offset;
                                        else t->len=0;
                                        t->u.offset=s_offset;
-                                       DBG("fixed to %d(%d)\n", t->u.offset, t->len);
                                }
                                s_offset=t->u.offset+t->len;
                                new_len-=t->len;
@@ -177,9 +172,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
                        case LUMP_NOP:
                                /* fix offset if overlapping on a deleted zone */
                                if (t->u.offset < s_offset){
-                                       DBG("overlapping zones (%d,%d)\n", s_offset, t->u.offset);
                                        t->u.offset=s_offset;
-                                       DBG("fixed to %d\n", t->u.offset);
                                }else
                                        s_offset=t->u.offset;
                                /* do nothing */
@@ -226,8 +219,6 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
        }
 /* copy msg adding/removing lumps */
        for (t=msg->add_rm;t;t=t->next){
-               DBG(" t=%x, op=%d, offset=%x, len=%d, s_offset=%x\n",
-                               t, t->op, t->u.offset, t->len, s_offset);
                switch(t->op){
                        case LUMP_ADD:
                                /* just add it here! */
diff --git a/main.c b/main.c
index a0c3354..ca35fef 100644 (file)
--- a/main.c
+++ b/main.c
@@ -30,7 +30,7 @@
 
 
 static char id[]="@(#) $Id$";
-static char version[]="ser 0.8.2";
+static char version[]="ser 0.8.3";
 static char flags[]="NOCR:"
 #ifdef NOCR
 "On"
index 77c6e99..47e208f 100644 (file)
@@ -382,16 +382,6 @@ error:
 }
 
 
-                       
-
-                       
-                       
-       
-               
-       
-       
-
-
 
 /* parses a via body, returns next via (for compact vias) & fills vb,
  * the buffer should be null terminated! */
@@ -686,3 +676,16 @@ error:
        return -1;
 }
 
+
+
+void free_uri(struct sip_uri* u)
+{
+       if (u){
+               if (u->user) free(u->user);
+               if (u->passwd) free(u->passwd);
+               if (u->host) free(u->host);
+               if (u->port) free(u->port);
+               if (u->params) free(u->params);
+               if (u->headers) free(u->headers);
+       }
+}
index 5d83b91..4dd7986 100644 (file)
@@ -102,6 +102,7 @@ char* parse_hostport(char* buf, char** host, short int* port);
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
 int parse_uri(char *buf, int len, struct sip_uri* uri);
+void free_uri(struct sip_uri* u);
 
 
 
diff --git a/proxy.c b/proxy.c
index 614f53d..46fa0a1 100644 (file)
--- a/proxy.c
+++ b/proxy.c
@@ -112,15 +112,52 @@ error:
 
 
 
+void free_hostent(struct hostent *dst)
+{
+       int r;
+       if (dst->h_name) free(dst->h_name);
+       if (dst->h_aliases){
+               for(r=0; dst->h_aliases[r]; r++)        free(dst->h_aliases[r]);
+               free(dst->h_aliases[r]);
+               free(dst->h_aliases);
+       }
+       if (dst->h_addr_list){
+               for (r=0; dst->h_addr_list[r];r++) free(dst->h_addr_list[r]);
+               free(dst->h_addr_list[r]);
+               free(dst->h_addr_list);
+       }
+}
+
+
+
+
 struct proxy_l* add_proxy(char* name, unsigned short port)
 {
        struct proxy_l* p;
        struct hostent* he;
        
        if ((p=find_proxy(name, port))!=0) return p;
+       if ((p=mk_proxy(name, port))==0) goto error;
+       /* add p to the proxy list */
+       p->next=proxies;
+       proxies=p;
+       return p;
+
+error:
+       return 0;
+}
+
+
+
+/* same as add_proxy, but it doesn't add the proxy to the list*/
+struct proxy_l* mk_proxy(char* name, unsigned short port)
+{
+       struct proxy_l* p;
+       struct hostent* he;
+       
        p=(struct proxy_l*) malloc(sizeof(struct proxy_l));
        if (p==0){
-               LOG(L_CRIT, "ERROR: add_proxy: memory allocation failure\n");
+               LOG(L_CRIT, "ERROR: mk_proxy: memory allocation failure\n");
                goto error;
        }
        memset(p,0,sizeof(struct proxy_l));
@@ -128,7 +165,7 @@ struct proxy_l* add_proxy(char* name, unsigned short port)
        p->port=port;
        he=gethostbyname(name);
        if (he==0){
-               LOG(L_CRIT, "ERROR: add_proxy: could not resolve hostname:"
+               LOG(L_CRIT, "ERROR: mk_proxy: could not resolve hostname:"
                                        " \"%s\"\n", name);
                free(p);
                goto error;
@@ -138,12 +175,14 @@ struct proxy_l* add_proxy(char* name, unsigned short port)
                goto error;
        }
        p->ok=1;
-       /* add p to the proxy list */
-       p->next=proxies;
-       proxies=p;
        return p;
-
 error:
        return 0;
 }
 
+
+
+void free_proxy(struct proxy_l* p)
+{
+       if (p) free_hostent(&p->host);
+}
diff --git a/proxy.h b/proxy.h
index 0b2fd98..dd1022f 100644 (file)
--- a/proxy.h
+++ b/proxy.h
@@ -28,6 +28,8 @@ struct proxy_l{
 extern struct proxy_l* proxies;
 
 struct proxy_l* add_proxy(char* name, unsigned short port);
+struct proxy_l* mk_proxy(char* name, unsigned short port);
+void free_proxy(struct proxy_l* p);
 
 
 #endif
diff --git a/route.c b/route.c
index ebb590c..4848390 100644 (file)
--- a/route.c
+++ b/route.c
@@ -135,6 +135,8 @@ static int fix_actions(struct action* a)
                                                        t->p1.data=p;
                                                        t->p1_type=PROXY_ST;
                                                        break;
+                                               case URIHOST_ST:
+                                                       break;
                                                default:
                                                        LOG(L_CRIT, "BUG: fix_actions: invalid type"
                                                                        "%d (should be string or number)\n",
@@ -178,11 +180,15 @@ static int fix_actions(struct action* a)
                                                        mod->exports->cmd_names[r]);
                                        if (mod->exports->fixup_pointers[r]){
                                                if (mod->exports->param_no[r]>0){
-                                                       ret=mod->exports->fixup_pointers[r](&t->p2.data,1);
+                                                       ret=mod->exports->fixup_pointers[r](&t->p2.data,
+                                                                                                                               1);
+                                                       t->p2_type=MODFIXUP_ST;
                                                        if (ret<0) return ret;
                                                }
                                                if (mod->exports->param_no[r]>1){
-                                                       ret=mod->exports->fixup_pointers[r](&t->p3.data,2);
+                                                       ret=mod->exports->fixup_pointers[r](&t->p3.data,
+                                                                                                                               2);
+                                                       t->p3_type=MODFIXUP_ST;
                                                        if (ret<0) return ret;
                                                }
                                        }
index 66f2843..406a16b 100644 (file)
@@ -15,7 +15,7 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
                SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
                SET_PORT_T, SET_URI_T, IF_T, MODULE_T };
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
-               EXPR_ST, ACTIONS_ST, CMDF_ST };
+               EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST };
 
        
 struct expr{
diff --git a/test/req2.sip b/test/req2.sip
new file mode 100644 (file)
index 0000000..c92085c
--- /dev/null
@@ -0,0 +1,5 @@
+INVITE sip:andrei@localhost:5061;a=b?c=d SIP/2.0
+Via: SIP/2.0/UDP localhost
+
+
+
diff --git a/test/test3.cfg b/test/test3.cfg
new file mode 100644 (file)
index 0000000..97af49b
--- /dev/null
@@ -0,0 +1,17 @@
+debug=9          # debug level (cmd line: -dddddddddd)
+check_via=yes     # (cmd. line: -v)
+dns=on           # (cmd. line: -r)
+rev_dns=yes      # (cmd. line: -R)
+fork=no          # (cmd. line: -D)
+log_stderror=yes # (cmd line: -E)
+# for more info: sip_router -h
+
+#modules
+loadmodule "modules/print/print.so"
+
+route{
+       #rewritehost("127.0.0.1");
+       print("trying forward to uri");
+       forward(uri:host,uri:port);
+       print("after forward");
+}