Browse Source

- added loadable module support (sr_module.*)
- bumped ver. no
(WARNING: not tested yet)

Andrei Pelinescu-Onciul 24 years ago
parent
commit
3bf76e49cd
9 changed files with 192 additions and 8 deletions
  1. 4 4
      Makefile
  2. 9 0
      action.c
  3. 4 1
      cfg.lex
  4. 28 0
      cfg.y
  5. 1 1
      main.c
  6. 7 0
      route_struct.c
  7. 2 2
      route_struct.h
  8. 93 0
      sr_module.c
  9. 44 0
      sr_module.h

+ 4 - 4
Makefile

@@ -35,7 +35,7 @@ YACC=bison
 YACC_FLAGS=-d -b cfg
 # on linux and freebsd keep it empty (e.g. LIBS= )
 # on solaris add -lxnet (e.g. LIBS= -lxnet)
-LIBS=-lfl
+LIBS=-lfl -ldl
 
 endif 
 ifeq  ($(ARCH), SunOS)
@@ -46,7 +46,7 @@ CFLAGS=-O2 -Wcast-align
 LEX=flex
 YACC=yacc
 YACC_FLAGS=-d -b cfg
-LIBS=-lfl -L/usr/local/lib -lxnet # or -lnsl -lsocket or -lglibc ?
+LIBS=-lfl -ldl -L/usr/local/lib -lxnet # or -lnsl -lsocket or -lglibc ?
 
 endif
 ifeq ($(ARCH), FreeBSD)
@@ -57,7 +57,7 @@ CFLAGS=-O2 -Wcast-align
 LEX=flex
 YACC=yacc
 YACC_FLAGS=-d -b cfg
-LIBS=-lfl
+LIBS=-lfl -ldl
 
 endif
 
@@ -70,7 +70,7 @@ YACC=bison
 YACC_FLAGS=-d -b cfg
 # on linux and freebsd keep it empty (e.g. LIBS= )
 # on solaris add -lxnet (e.g. LIBS= -lxnet)
-LIBS=-lfl
+LIBS=-lfl -ldl
 
 endif
 

+ 9 - 0
action.c

@@ -13,6 +13,7 @@
 #include "udp_server.h"
 #include "route.h"
 #include "msg_parser.h"
+#include "sr_module.h"
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -274,6 +275,14 @@ int do_action(struct action* a, struct sip_msg* msg)
 					}
 				}
 			break;
+		case MODULE_T:
+			if ( ((a->p1_type==CMDF_ST)&&a->p1.data)&&
+					((a->p2_type==STRING_ST)&&a->p2.data) ){
+				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data);
+			}else{
+				LOG(L_CRIT,"BUG: do_action: bad module call\n");
+			}
+			break;
 		default:
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
 	}

+ 4 - 1
cfg.lex

@@ -80,13 +80,15 @@ PORT	port
 CHILDREN children
 CHECK_VIA	check_via
 
+LOADMODULE	loadmodule
+
 /* values */
 YES			"yes"|"true"|"on"|"enable"
 NO			"no"|"false"|"off"|"disable"
 
 LETTER		[a-zA-Z]
 DIGIT		[0-9]
-ALPHANUM	{LETTER}|{DIGIT}
+ALPHANUM	{LETTER}|{DIGIT}|[_]
 NUMBER		{DIGIT}+
 ID			{LETTER}{ALPHANUM}*
 QUOTES		\"
@@ -146,6 +148,7 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{PORT}	{ count(); yylval.strval=yytext; return PORT; }
 <INITIAL>{CHILDREN}	{ count(); yylval.strval=yytext; return CHILDREN; }
 <INITIAL>{CHECK_VIA}	{ count(); yylval.strval=yytext; return CHECK_VIA; }
+<INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
 
 <INITIAL>{EQUAL}	{ count(); return EQUAL; }
 <INITIAL>{EQUAL_T}	{ count(); return EQUAL_T; }

+ 28 - 0
cfg.y

@@ -17,6 +17,7 @@
 #include "globals.h"
 #include "route.h"
 #include "dprint.h"
+#include "sr_module.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
@@ -24,6 +25,7 @@
 
 void yyerror(char* s);
 char* tmp;
+void* f_tmp;
 
 %}
 
@@ -71,6 +73,7 @@ char* tmp;
 %token PORT
 %token CHILDREN
 %token CHECK_VIA
+%token LOADMODULE
 
 
 
@@ -125,6 +128,7 @@ statements:	statements statement {}
 	;
 
 statement:	assign_stm 
+		| module_stm
 		| route_stm 
 		| CR	/* null statement*/
 	;
@@ -205,6 +209,14 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| error EQUAL { yyerror("unknown config variable"); }
 	;
 
+module_stm:	LOADMODULE STRING	{ DBG("loading module %s", $2);
+		  						  if (load_module($2)!=0){
+								  		yyerror("failed to load module");
+								  }
+								}
+		 |	LOADMODULE error	{ yyerror("string expected");  }
+		 ;
+
 
 ipv4:	NUMBER DOT NUMBER DOT NUMBER DOT NUMBER { 
 											if (($1>255) || ($1<0) ||
@@ -542,6 +554,22 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 										"string expected"); }
+		| ID LPAREN STRING RPAREN { DBG(" %s - doing nothing", $1);
+									f_tmp=find_export($1);
+									if (f_tmp==0){
+										yyerror("unknown command %s, missing"
+										" loadmodule?\n");
+										$$=0;
+									}else{
+										$$=mk_action(	MODULE_T,
+														CMDF_ST,
+														STRING_ST,
+														f_tmp,
+														$3
+													);
+									}
+								  }
+		| ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); }
 		| if_cmd		{ $$=$1; }
 	;
 

+ 1 - 1
main.c

@@ -30,7 +30,7 @@
 
 
 static char id[]="@(#) $Id$";
-static char version[]="ser 0.7";
+static char version[]="ser 0.8.1-plugins";
 static char flags[]="NOCR:"
 #ifdef NOCR
 "On"

+ 7 - 0
route_struct.c

@@ -57,6 +57,7 @@ struct action* mk_action(int type, int p1_type, int p2_type, void* p1, void* p2)
 	struct action* a;
 	a=(struct action*)malloc(sizeof(struct action));
 	if (a==0) goto  error;
+	memset(a,0,sizeof(struct action));
 	a->type=type;
 	a->p1_type=p1_type;
 	a->p2_type=p2_type;
@@ -279,6 +280,9 @@ void print_action(struct action* a)
 			case IF_T:
 					DBG("if (");
 					break;
+			case MODULE_T:
+					DBG(" external_module_call(");
+					break;
 			default:
 					DBG("UNKNOWN(");
 		}
@@ -298,6 +302,9 @@ void print_action(struct action* a)
 			case ACTIONS_ST:
 					print_action((struct action*)t->p1.data);
 					break;
+			case CMDF_ST:
+					DBG("f_ptr<%x>",t->p1.data);
+					break;
 			default:
 					DBG("type<%d>", t->p1_type);
 		}

+ 2 - 2
route_struct.h

@@ -13,9 +13,9 @@ enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O, ACTION_O, NUMBER_O};
 
 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 };
+		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 };
+		EXPR_ST, ACTIONS_ST, CMDF_ST };
 
 	
 struct expr{

+ 93 - 0
sr_module.c

@@ -0,0 +1,93 @@
+/* $Id$
+ */
+
+#include "sr_module.h"
+#include "dprint.h"
+
+#include <dlfcn.h>
+#include <strings.h>
+#include <stdlib.h>
+
+
+static struct sr_module* modules=0;
+
+
+
+/* returns 0 on success , <0 on error */
+int load_module(char* path)
+{
+	void* handle;
+	char* error;
+	struct sr_module* t, *mod;
+	struct module_exports* e;
+	struct module_exports* (*mod_register)();
+	
+	handle=dlopen(path, RTLD_NOW); /* resolve all symbols now */
+	if (handle==0){
+		LOG(L_ERR, "ERROR: load_module: could not open module <%s>: %s\n",
+					path, dlerror() );
+		goto error;
+	}
+	
+	for(t=modules;t; t=t->next){
+		if (t->handle==handle){
+			LOG(L_WARN, "WARNING: load_module: attempting to load the same"
+						" module twice (%s)\n", path);
+			goto skip;
+		}
+	}
+	/* launch register */
+	mod_register = dlsym(handle, "mod_register");
+	if ( (error =dlerror())!=0 ){
+		LOG(L_ERR, "ERROR: load_module: %s\n", error);
+		goto error1;
+	}
+	
+	e=(*mod_register)();
+	if (e==0){
+		LOG(L_ERR, "ERROR: mod_register returned null\n");
+		goto error1;
+	}
+	/* add module to the list */
+	if ((mod=malloc(sizeof(struct sr_module)))==0){
+		LOG(L_ERR, "load_module: memory allocation failure\n");
+		goto error1;
+	}
+	memset(mod,0, sizeof(struct sr_module));
+	mod->path=path;
+	mod->handle=handle;
+	mod->exports=e;
+	mod->next=modules;
+	modules=mod;
+	return 0;
+
+error1:
+	dlclose(handle);
+error:
+skip:
+	return -1;
+}
+
+
+
+/* searches the module list and returns a pointer to the "name" function or
+ * 0 if not found */
+cmd_function find_export(char* name)
+{
+	struct sr_module* t;
+	int r;
+
+	for(t=modules;t;t=t->next){
+		for(r=0;r<t->exports->cmd_no;r++){
+			if(strcmp(name, t->exports->cmd_names[r])==0){
+				DBG("find_export: found <%s> in module %s [%s]\n",
+						name, t->exports->name, t->path);
+				return t->exports->cmd_pointers[r];
+			}
+		}
+	}
+	DBG("find_export: <%s> not found \n", name);
+	return 0;
+}
+
+	

+ 44 - 0
sr_module.h

@@ -0,0 +1,44 @@
+/* $Id$
+ *
+ * modules/plugin strtuctures declarations
+ *
+ */
+
+#ifndef sr_module
+
+#include "msg_parser.h" /* for sip_msg */
+
+typedef  int (*cmd_function)(struct sip_msg*, char*);
+typedef  int (*response_function)(struct sip_msg*);
+
+struct module_exports{
+	char* name; /* null terminated module name */
+	char** cmd_names;
+	cmd_function* cmd_pointers;
+	int cmd_no; /* number of registered commands 
+				   (size of cmd_{names,pointers}*/
+	response_function response_f; /* function used for responses,
+											   returns yes or no */
+};
+
+struct sr_module{
+	char* path;
+	void* handle;
+	struct module_exports* exports;
+	struct sr_module* next;
+};
+
+
+int load_module(char* path);
+cmd_function find_export(char* name);
+
+/* modules function prototypes:
+ * struct module_exports* mod_register();
+ * int   foo_cmd(struct sip_msg* msg, char* param);
+ *  - returns >0 if ok , <0 on error, 0 to stop processing (==DROP)
+ * int   response_f(struct sip_msg* msg)
+ *  - returns >0 if ok, 0 to drop message
+ */
+
+
+#endif