... | ... |
@@ -35,7 +35,7 @@ YACC=bison |
35 | 35 |
YACC_FLAGS=-d -b cfg |
36 | 36 |
# on linux and freebsd keep it empty (e.g. LIBS= ) |
37 | 37 |
# on solaris add -lxnet (e.g. LIBS= -lxnet) |
38 |
-LIBS=-lfl |
|
38 |
+LIBS=-lfl -ldl |
|
39 | 39 |
|
40 | 40 |
endif |
41 | 41 |
ifeq ($(ARCH), SunOS) |
... | ... |
@@ -46,7 +46,7 @@ CFLAGS=-O2 -Wcast-align |
46 | 46 |
LEX=flex |
47 | 47 |
YACC=yacc |
48 | 48 |
YACC_FLAGS=-d -b cfg |
49 |
-LIBS=-lfl -L/usr/local/lib -lxnet # or -lnsl -lsocket or -lglibc ? |
|
49 |
+LIBS=-lfl -ldl -L/usr/local/lib -lxnet # or -lnsl -lsocket or -lglibc ? |
|
50 | 50 |
|
51 | 51 |
endif |
52 | 52 |
ifeq ($(ARCH), FreeBSD) |
... | ... |
@@ -57,7 +57,7 @@ CFLAGS=-O2 -Wcast-align |
57 | 57 |
LEX=flex |
58 | 58 |
YACC=yacc |
59 | 59 |
YACC_FLAGS=-d -b cfg |
60 |
-LIBS=-lfl |
|
60 |
+LIBS=-lfl -ldl |
|
61 | 61 |
|
62 | 62 |
endif |
63 | 63 |
|
... | ... |
@@ -70,7 +70,7 @@ YACC=bison |
70 | 70 |
YACC_FLAGS=-d -b cfg |
71 | 71 |
# on linux and freebsd keep it empty (e.g. LIBS= ) |
72 | 72 |
# on solaris add -lxnet (e.g. LIBS= -lxnet) |
73 |
-LIBS=-lfl |
|
73 |
+LIBS=-lfl -ldl |
|
74 | 74 |
|
75 | 75 |
endif |
76 | 76 |
|
... | ... |
@@ -13,6 +13,7 @@ |
13 | 13 |
#include "udp_server.h" |
14 | 14 |
#include "route.h" |
15 | 15 |
#include "msg_parser.h" |
16 |
+#include "sr_module.h" |
|
16 | 17 |
|
17 | 18 |
#include <sys/types.h> |
18 | 19 |
#include <sys/socket.h> |
... | ... |
@@ -274,6 +275,14 @@ int do_action(struct action* a, struct sip_msg* msg) |
274 | 275 |
} |
275 | 276 |
} |
276 | 277 |
break; |
278 |
+ case MODULE_T: |
|
279 |
+ if ( ((a->p1_type==CMDF_ST)&&a->p1.data)&& |
|
280 |
+ ((a->p2_type==STRING_ST)&&a->p2.data) ){ |
|
281 |
+ ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data); |
|
282 |
+ }else{ |
|
283 |
+ LOG(L_CRIT,"BUG: do_action: bad module call\n"); |
|
284 |
+ } |
|
285 |
+ break; |
|
277 | 286 |
default: |
278 | 287 |
LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type); |
279 | 288 |
} |
... | ... |
@@ -80,13 +80,15 @@ PORT port |
80 | 80 |
CHILDREN children |
81 | 81 |
CHECK_VIA check_via |
82 | 82 |
|
83 |
+LOADMODULE loadmodule |
|
84 |
+ |
|
83 | 85 |
/* values */ |
84 | 86 |
YES "yes"|"true"|"on"|"enable" |
85 | 87 |
NO "no"|"false"|"off"|"disable" |
86 | 88 |
|
87 | 89 |
LETTER [a-zA-Z] |
88 | 90 |
DIGIT [0-9] |
89 |
-ALPHANUM {LETTER}|{DIGIT} |
|
91 |
+ALPHANUM {LETTER}|{DIGIT}|[_] |
|
90 | 92 |
NUMBER {DIGIT}+ |
91 | 93 |
ID {LETTER}{ALPHANUM}* |
92 | 94 |
QUOTES \" |
... | ... |
@@ -146,6 +148,7 @@ EAT_ABLE [\ \t\b\r] |
146 | 148 |
<INITIAL>{PORT} { count(); yylval.strval=yytext; return PORT; } |
147 | 149 |
<INITIAL>{CHILDREN} { count(); yylval.strval=yytext; return CHILDREN; } |
148 | 150 |
<INITIAL>{CHECK_VIA} { count(); yylval.strval=yytext; return CHECK_VIA; } |
151 |
+<INITIAL>{LOADMODULE} { count(); yylval.strval=yytext; return LOADMODULE; } |
|
149 | 152 |
|
150 | 153 |
<INITIAL>{EQUAL} { count(); return EQUAL; } |
151 | 154 |
<INITIAL>{EQUAL_T} { count(); return EQUAL_T; } |
... | ... |
@@ -17,6 +17,7 @@ |
17 | 17 |
#include "globals.h" |
18 | 18 |
#include "route.h" |
19 | 19 |
#include "dprint.h" |
20 |
+#include "sr_module.h" |
|
20 | 21 |
|
21 | 22 |
#ifdef DEBUG_DMALLOC |
22 | 23 |
#include <dmalloc.h> |
... | ... |
@@ -24,6 +25,7 @@ |
24 | 25 |
|
25 | 26 |
void yyerror(char* s); |
26 | 27 |
char* tmp; |
28 |
+void* f_tmp; |
|
27 | 29 |
|
28 | 30 |
%} |
29 | 31 |
|
... | ... |
@@ -71,6 +73,7 @@ char* tmp; |
71 | 73 |
%token PORT |
72 | 74 |
%token CHILDREN |
73 | 75 |
%token CHECK_VIA |
76 |
+%token LOADMODULE |
|
74 | 77 |
|
75 | 78 |
|
76 | 79 |
|
... | ... |
@@ -125,6 +128,7 @@ statements: statements statement {} |
125 | 128 |
; |
126 | 129 |
|
127 | 130 |
statement: assign_stm |
131 |
+ | module_stm |
|
128 | 132 |
| route_stm |
129 | 133 |
| CR /* null statement*/ |
130 | 134 |
; |
... | ... |
@@ -205,6 +209,14 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
205 | 209 |
| error EQUAL { yyerror("unknown config variable"); } |
206 | 210 |
; |
207 | 211 |
|
212 |
+module_stm: LOADMODULE STRING { DBG("loading module %s", $2); |
|
213 |
+ if (load_module($2)!=0){ |
|
214 |
+ yyerror("failed to load module"); |
|
215 |
+ } |
|
216 |
+ } |
|
217 |
+ | LOADMODULE error { yyerror("string expected"); } |
|
218 |
+ ; |
|
219 |
+ |
|
208 | 220 |
|
209 | 221 |
ipv4: NUMBER DOT NUMBER DOT NUMBER DOT NUMBER { |
210 | 222 |
if (($1>255) || ($1<0) || |
... | ... |
@@ -542,6 +554,22 @@ cmd: FORWARD LPAREN host RPAREN { $$=mk_action( FORWARD_T, |
542 | 554 |
| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); } |
543 | 555 |
| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, " |
544 | 556 |
"string expected"); } |
557 |
+ | ID LPAREN STRING RPAREN { DBG(" %s - doing nothing", $1); |
|
558 |
+ f_tmp=find_export($1); |
|
559 |
+ if (f_tmp==0){ |
|
560 |
+ yyerror("unknown command %s, missing" |
|
561 |
+ " loadmodule?\n"); |
|
562 |
+ $$=0; |
|
563 |
+ }else{ |
|
564 |
+ $$=mk_action( MODULE_T, |
|
565 |
+ CMDF_ST, |
|
566 |
+ STRING_ST, |
|
567 |
+ f_tmp, |
|
568 |
+ $3 |
|
569 |
+ ); |
|
570 |
+ } |
|
571 |
+ } |
|
572 |
+ | ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); } |
|
545 | 573 |
| if_cmd { $$=$1; } |
546 | 574 |
; |
547 | 575 |
|
... | ... |
@@ -57,6 +57,7 @@ struct action* mk_action(int type, int p1_type, int p2_type, void* p1, void* p2) |
57 | 57 |
struct action* a; |
58 | 58 |
a=(struct action*)malloc(sizeof(struct action)); |
59 | 59 |
if (a==0) goto error; |
60 |
+ memset(a,0,sizeof(struct action)); |
|
60 | 61 |
a->type=type; |
61 | 62 |
a->p1_type=p1_type; |
62 | 63 |
a->p2_type=p2_type; |
... | ... |
@@ -279,6 +280,9 @@ void print_action(struct action* a) |
279 | 280 |
case IF_T: |
280 | 281 |
DBG("if ("); |
281 | 282 |
break; |
283 |
+ case MODULE_T: |
|
284 |
+ DBG(" external_module_call("); |
|
285 |
+ break; |
|
282 | 286 |
default: |
283 | 287 |
DBG("UNKNOWN("); |
284 | 288 |
} |
... | ... |
@@ -298,6 +302,9 @@ void print_action(struct action* a) |
298 | 302 |
case ACTIONS_ST: |
299 | 303 |
print_action((struct action*)t->p1.data); |
300 | 304 |
break; |
305 |
+ case CMDF_ST: |
|
306 |
+ DBG("f_ptr<%x>",t->p1.data); |
|
307 |
+ break; |
|
301 | 308 |
default: |
302 | 309 |
DBG("type<%d>", t->p1_type); |
303 | 310 |
} |
... | ... |
@@ -13,9 +13,9 @@ enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O, ACTION_O, NUMBER_O}; |
13 | 13 |
|
14 | 14 |
enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, |
15 | 15 |
SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, |
16 |
- SET_PORT_T, SET_URI_T, IF_T }; |
|
16 |
+ SET_PORT_T, SET_URI_T, IF_T, MODULE_T }; |
|
17 | 17 |
enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST, |
18 |
- EXPR_ST, ACTIONS_ST }; |
|
18 |
+ EXPR_ST, ACTIONS_ST, CMDF_ST }; |
|
19 | 19 |
|
20 | 20 |
|
21 | 21 |
struct expr{ |
22 | 22 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,93 @@ |
1 |
+/* $Id$ |
|
2 |
+ */ |
|
3 |
+ |
|
4 |
+#include "sr_module.h" |
|
5 |
+#include "dprint.h" |
|
6 |
+ |
|
7 |
+#include <dlfcn.h> |
|
8 |
+#include <strings.h> |
|
9 |
+#include <stdlib.h> |
|
10 |
+ |
|
11 |
+ |
|
12 |
+static struct sr_module* modules=0; |
|
13 |
+ |
|
14 |
+ |
|
15 |
+ |
|
16 |
+/* returns 0 on success , <0 on error */ |
|
17 |
+int load_module(char* path) |
|
18 |
+{ |
|
19 |
+ void* handle; |
|
20 |
+ char* error; |
|
21 |
+ struct sr_module* t, *mod; |
|
22 |
+ struct module_exports* e; |
|
23 |
+ struct module_exports* (*mod_register)(); |
|
24 |
+ |
|
25 |
+ handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */ |
|
26 |
+ if (handle==0){ |
|
27 |
+ LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n", |
|
28 |
+ path, dlerror() ); |
|
29 |
+ goto error; |
|
30 |
+ } |
|
31 |
+ |
|
32 |
+ for(t=modules;t; t=t->next){ |
|
33 |
+ if (t->handle==handle){ |
|
34 |
+ LOG(L_WARN, "WARNING: load_module: attempting to load the same" |
|
35 |
+ " module twice (%s)\n", path); |
|
36 |
+ goto skip; |
|
37 |
+ } |
|
38 |
+ } |
|
39 |
+ /* launch register */ |
|
40 |
+ mod_register = dlsym(handle, "mod_register"); |
|
41 |
+ if ( (error =dlerror())!=0 ){ |
|
42 |
+ LOG(L_ERR, "ERROR: load_module: %s\n", error); |
|
43 |
+ goto error1; |
|
44 |
+ } |
|
45 |
+ |
|
46 |
+ e=(*mod_register)(); |
|
47 |
+ if (e==0){ |
|
48 |
+ LOG(L_ERR, "ERROR: mod_register returned null\n"); |
|
49 |
+ goto error1; |
|
50 |
+ } |
|
51 |
+ /* add module to the list */ |
|
52 |
+ if ((mod=malloc(sizeof(struct sr_module)))==0){ |
|
53 |
+ LOG(L_ERR, "load_module: memory allocation failure\n"); |
|
54 |
+ goto error1; |
|
55 |
+ } |
|
56 |
+ memset(mod,0, sizeof(struct sr_module)); |
|
57 |
+ mod->path=path; |
|
58 |
+ mod->handle=handle; |
|
59 |
+ mod->exports=e; |
|
60 |
+ mod->next=modules; |
|
61 |
+ modules=mod; |
|
62 |
+ return 0; |
|
63 |
+ |
|
64 |
+error1: |
|
65 |
+ dlclose(handle); |
|
66 |
+error: |
|
67 |
+skip: |
|
68 |
+ return -1; |
|
69 |
+} |
|
70 |
+ |
|
71 |
+ |
|
72 |
+ |
|
73 |
+/* searches the module list and returns a pointer to the "name" function or |
|
74 |
+ * 0 if not found */ |
|
75 |
+cmd_function find_export(char* name) |
|
76 |
+{ |
|
77 |
+ struct sr_module* t; |
|
78 |
+ int r; |
|
79 |
+ |
|
80 |
+ for(t=modules;t;t=t->next){ |
|
81 |
+ for(r=0;r<t->exports->cmd_no;r++){ |
|
82 |
+ if(strcmp(name, t->exports->cmd_names[r])==0){ |
|
83 |
+ DBG("find_export: found <%s> in module %s [%s]\n", |
|
84 |
+ name, t->exports->name, t->path); |
|
85 |
+ return t->exports->cmd_pointers[r]; |
|
86 |
+ } |
|
87 |
+ } |
|
88 |
+ } |
|
89 |
+ DBG("find_export: <%s> not found \n", name); |
|
90 |
+ return 0; |
|
91 |
+} |
|
92 |
+ |
|
93 |
+ |
0 | 94 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,44 @@ |
1 |
+/* $Id$ |
|
2 |
+ * |
|
3 |
+ * modules/plugin strtuctures declarations |
|
4 |
+ * |
|
5 |
+ */ |
|
6 |
+ |
|
7 |
+#ifndef sr_module |
|
8 |
+ |
|
9 |
+#include "msg_parser.h" /* for sip_msg */ |
|
10 |
+ |
|
11 |
+typedef int (*cmd_function)(struct sip_msg*, char*); |
|
12 |
+typedef int (*response_function)(struct sip_msg*); |
|
13 |
+ |
|
14 |
+struct module_exports{ |
|
15 |
+ char* name; /* null terminated module name */ |
|
16 |
+ char** cmd_names; |
|
17 |
+ cmd_function* cmd_pointers; |
|
18 |
+ int cmd_no; /* number of registered commands |
|
19 |
+ (size of cmd_{names,pointers}*/ |
|
20 |
+ response_function response_f; /* function used for responses, |
|
21 |
+ returns yes or no */ |
|
22 |
+}; |
|
23 |
+ |
|
24 |
+struct sr_module{ |
|
25 |
+ char* path; |
|
26 |
+ void* handle; |
|
27 |
+ struct module_exports* exports; |
|
28 |
+ struct sr_module* next; |
|
29 |
+}; |
|
30 |
+ |
|
31 |
+ |
|
32 |
+int load_module(char* path); |
|
33 |
+cmd_function find_export(char* name); |
|
34 |
+ |
|
35 |
+/* modules function prototypes: |
|
36 |
+ * struct module_exports* mod_register(); |
|
37 |
+ * int foo_cmd(struct sip_msg* msg, char* param); |
|
38 |
+ * - returns >0 if ok , <0 on error, 0 to stop processing (==DROP) |
|
39 |
+ * int response_f(struct sip_msg* msg) |
|
40 |
+ * - returns >0 if ok, 0 to drop message |
|
41 |
+ */ |
|
42 |
+ |
|
43 |
+ |
|
44 |
+#endif |