00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <sys/types.h>
00029 #include <regex.h>
00030
00031 #include "../../sr_module.h"
00032 #include "../../str.h"
00033 #include "../../dprint.h"
00034 #include "../../mem/mem.h"
00035 #include "../../modules/tm/tm_load.h"
00036 #include "rd_funcs.h"
00037 #include "rd_filter.h"
00038
00039 MODULE_VERSION
00040
00041
00042 struct tm_binds rd_tmb;
00043 cmd_function rd_acc_fct = 0;
00044
00045
00046 char *acc_db_table = "acc";
00047 char *acc_fct_s = "acc_log_request";
00048
00049
00050 char *deny_filter_s = 0;
00051 char *accept_filter_s = 0;
00052 char *def_filter_s = 0;
00053
00054 unsigned int bflags = 0;
00055
00056 #define ACCEPT_RULE_STR "accept"
00057 #define DENY_RULE_STR "deny"
00058
00059
00060
00061 static int redirect_init(void);
00062 static int w_set_deny(struct sip_msg* msg, char *dir, char *foo);
00063 static int w_set_accept(struct sip_msg* msg, char *dir, char *foo);
00064 static int w_get_redirect1(struct sip_msg* msg, char *dir, char *foo);
00065 static int w_get_redirect2(struct sip_msg* msg, char *dir, char *foo);
00066 static int regexp_compile(char *re_s, regex_t **re);
00067 static int get_redirect_fixup(void** param, int param_no);
00068 static int setf_fixup(void** param, int param_no);
00069
00070
00071 static cmd_export_t cmds[] = {
00072 {"set_deny_filter", (cmd_function)w_set_deny, 2, setf_fixup, 0,
00073 FAILURE_ROUTE },
00074 {"set_accept_filter", (cmd_function)w_set_accept, 2, setf_fixup, 0,
00075 FAILURE_ROUTE },
00076 {"get_redirects", (cmd_function)w_get_redirect2, 2, get_redirect_fixup, 0,
00077 FAILURE_ROUTE },
00078 {"get_redirects", (cmd_function)w_get_redirect1, 1, get_redirect_fixup, 0,
00079 FAILURE_ROUTE },
00080 {0, 0, 0, 0, 0, 0}
00081 };
00082
00083 static param_export_t params[] = {
00084 {"deny_filter", STR_PARAM, &deny_filter_s },
00085 {"accept_filter", STR_PARAM, &accept_filter_s },
00086 {"default_filter", STR_PARAM, &def_filter_s },
00087 {"acc_function", STR_PARAM, &acc_fct_s },
00088 {"acc_db_table", STR_PARAM, &acc_db_table },
00089 {"bflags", INT_PARAM, &bflags },
00090 {0, 0, 0}
00091 };
00092
00093
00094 struct module_exports exports = {
00095 "uac_redirect",
00096 DEFAULT_DLFLAGS,
00097 cmds,
00098 params,
00099 0,
00100 0,
00101 0,
00102 0,
00103 redirect_init,
00104 0,
00105 0,
00106 (child_init_function) 0
00107 };
00108
00109
00110
00111 int get_nr_max(char *s, unsigned char *max)
00112 {
00113 unsigned short nr;
00114 int err;
00115
00116 if ( s[0]=='*' && s[1]==0 ) {
00117
00118 *max = 0;
00119 return 0;
00120 } else {
00121
00122 nr = str2s(s, strlen(s), &err);
00123 if (err==0){
00124 if (nr>255){
00125 LM_ERR("number too big <%d> (max=255)\n",nr);
00126 return -1;
00127 }
00128 *max = (unsigned char)nr;
00129 return 0;
00130 }else{
00131 LM_ERR("bad number <%s>\n",s);
00132 return -1;
00133 }
00134 }
00135 }
00136
00137
00138 static int get_redirect_fixup(void** param, int param_no)
00139 {
00140 unsigned char maxb,maxt;
00141 struct acc_param *accp;
00142 cmd_function fct;
00143 char *p;
00144 char *s;
00145
00146 s = (char*)*param;
00147 if (param_no==1) {
00148 if ( (p=strchr(s,':'))!=0 ) {
00149
00150 *p = 0;
00151 if (get_nr_max(p+1, &maxb)!=0)
00152 return E_UNSPEC;
00153 } else {
00154 maxb = 0;
00155 }
00156
00157
00158 if (get_nr_max(s, &maxt)!=0)
00159 return E_UNSPEC;
00160
00161 pkg_free(*param);
00162 *param=(void*)(long)( (((unsigned short)maxt)<<8) | maxb);
00163
00164 } else if (param_no==2) {
00165
00166 if (rd_acc_fct!=0)
00167 return 0;
00168
00169 if (acc_fct_s==0 || acc_fct_s[0]==0) {
00170 LM_ERR("acc support enabled, but no acc function defined\n");
00171 return E_UNSPEC;
00172 }
00173 fct = find_export(acc_fct_s, 2, REQUEST_ROUTE);
00174 if ( fct==0 )
00175 fct = find_export(acc_fct_s, 1, REQUEST_ROUTE);
00176 if ( fct==0 ) {
00177 LM_ERR("cannot import %s function; is acc loaded and proper "
00178 "compiled?\n", acc_fct_s);
00179 return E_UNSPEC;
00180 }
00181 rd_acc_fct = fct;
00182
00183 accp = (struct acc_param*)pkg_malloc(sizeof(struct acc_param));
00184 if (accp==0) {
00185 LM_ERR("no more pkg mem\n");
00186 return E_UNSPEC;
00187 }
00188 memset( accp, 0, sizeof(struct acc_param));
00189 if (s!=0 && *s!=0) {
00190 accp->reason.s = s;
00191 accp->reason.len = strlen(s);
00192 } else {
00193 accp->reason.s = "n/a";
00194 accp->reason.len = 3;
00195 }
00196 *param=(void*)accp;
00197 }
00198
00199 return 0;
00200 }
00201
00202
00203 static int setf_fixup(void** param, int param_no)
00204 {
00205 unsigned short nr;
00206 regex_t *filter;
00207 char *s;
00208
00209 s = (char*)*param;
00210 if (param_no==1) {
00211
00212 if (regexp_compile( s, &filter)<0) {
00213 LM_ERR("cannot init filter <%s>\n", s);
00214 return E_BAD_RE;
00215 }
00216 pkg_free(*param);
00217 *param = (void*)filter;
00218 } else if (param_no==2) {
00219 if (s==0 || s[0]==0) {
00220 nr = 0;
00221 } else if (strcasecmp(s,"reset_all")==0) {
00222 nr = RESET_ADDED|RESET_DEFAULT;
00223 } else if (strcasecmp(s,"reset_default")==0) {
00224 nr = RESET_DEFAULT;
00225 } else if (strcasecmp(s,"reset_added")==0) {
00226 nr = RESET_ADDED;
00227 } else {
00228 LM_ERR("unknown reset type <%s>\n",s);
00229 return E_UNSPEC;
00230 }
00231 pkg_free(*param);
00232 *param = (void*)(long)nr;
00233 }
00234
00235 return 0;
00236 }
00237
00238
00239
00240 static int regexp_compile(char *re_s, regex_t **re)
00241 {
00242 *re = 0;
00243 if (re_s==0 || strlen(re_s)==0 ) {
00244 return 0;
00245 } else {
00246 if ((*re=pkg_malloc(sizeof(regex_t)))==0)
00247 return E_OUT_OF_MEM;
00248 if (regcomp(*re, re_s, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ){
00249 pkg_free(*re);
00250 *re = 0;
00251 LM_ERR("regexp_compile:bad regexp <%s>\n", re_s);
00252 return E_BAD_RE;
00253 }
00254 }
00255 return 0;
00256 }
00257
00258
00259
00260 static int redirect_init(void)
00261 {
00262 regex_t *filter;
00263
00264
00265 if (load_tm_api(&rd_tmb)!=0) {
00266 LM_ERR("failed to load TM API\n");
00267 goto error;
00268 }
00269
00270
00271 init_filters();
00272
00273
00274 if (def_filter_s) {
00275 if ( !strcasecmp(def_filter_s,ACCEPT_RULE_STR) ) {
00276 set_default_rule( ACCEPT_RULE );
00277 } else if ( !strcasecmp(def_filter_s,DENY_RULE_STR) ) {
00278 set_default_rule( DENY_RULE );
00279 } else {
00280 LM_ERR("unknown default filter <%s>\n",def_filter_s);
00281 }
00282 }
00283
00284
00285 if (regexp_compile(accept_filter_s, &filter)<0) {
00286 LM_ERR("failed to init accept filter\n");
00287 goto error;
00288 }
00289 add_default_filter( ACCEPT_FILTER, filter);
00290
00291
00292 if (regexp_compile(deny_filter_s, &filter)<0) {
00293 LM_ERR("failed to init deny filter\n");
00294 goto error;
00295 }
00296 add_default_filter( DENY_FILTER, filter);
00297
00298 return 0;
00299 error:
00300 return -1;
00301 }
00302
00303
00304 static inline void msg_tracer(struct sip_msg* msg, int reset)
00305 {
00306 static unsigned int id = 0;
00307 static unsigned int set = 0;
00308
00309 if (reset) {
00310 set = 0;
00311 } else {
00312 if (set) {
00313 if (id!=msg->id) {
00314 LM_WARN("filters set but not used -> reseting to default\n");
00315 reset_filters();
00316 id = msg->id;
00317 }
00318 } else {
00319 id = msg->id;
00320 set = 1;
00321 }
00322 }
00323 }
00324
00325
00326 static int w_set_deny(struct sip_msg* msg, char *re, char *flags)
00327 {
00328 msg_tracer( msg, 0);
00329 return (add_filter( DENY_FILTER, (regex_t*)re, (int)(long)flags)==0)?1:-1;
00330 }
00331
00332
00333 static int w_set_accept(struct sip_msg* msg, char *re, char *flags)
00334 {
00335 msg_tracer( msg, 0);
00336 return (add_filter( ACCEPT_FILTER, (regex_t*)re, (int)(long)flags)==0)?1:-1;
00337 }
00338
00339
00340 static int w_get_redirect2(struct sip_msg* msg, char *max_c, char *reason)
00341 {
00342 int n;
00343 unsigned short max;
00344
00345 msg_tracer( msg, 0);
00346
00347 max = (unsigned short)(long)max_c;
00348 n = get_redirect(msg , (max>>8)&0xff, max&0xff, (struct acc_param*)reason, bflags);
00349 reset_filters();
00350
00351 msg_tracer( msg, 1);
00352
00353 return n;
00354 }
00355
00356
00357 static int w_get_redirect1(struct sip_msg* msg, char *max_c, char *foo)
00358 {
00359 return w_get_redirect2(msg, max_c, 0);
00360 }
00361