Browse code

- extend check_user_blacklist function to load the number that should checked from any pseudo-variable - extend check_user_blacklist function to check against a given table name - the old normal interface was not changed - based on a patch from Helmut Kuper, helmut dot kuper at ewetel dot de - available functions now skip over any non-digits in front of the matched URI user, instead of returning without match (similar to carrierroute) - small log cleanups and optimizations - add documentation for the new interface

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@4100 689a6050-402a-0410-94f2-e92a70836424

Henning Westerholt authored on 28/04/2008 17:12:13
Showing 4 changed files
... ...
@@ -36,7 +36,7 @@ Henning Westerholt
36 36
         1.4. Exported Functions
37 37
 
38 38
               1.4.1. check_user_blacklist (string user, string
39
-                      domain)
39
+                      domain, string number, string table)
40 40
 
41 41
               1.4.2. check_blacklist (string table)
42 42
 
... ...
@@ -138,13 +138,17 @@ modparam("userblacklist", "use_domain", 0)
138 138
 
139 139
 1.4. Exported Functions
140 140
 
141
-1.4.1.  check_user_blacklist (string user, string domain)
142
-
143
-   Finds the longest prefix that matches the request URI for the
144
-   given user and domain name in the database. If a match is found
145
-   and it is not set to whitelist, false is returned. Otherwise,
146
-   true is returned. Pseudo-variables or AVPs can be used for both
147
-   parameters.
141
+1.4.1.  check_user_blacklist (string user, string domain, string
142
+number, string table)
143
+
144
+   Finds the longest prefix that matches the request URI user (or
145
+   the number parameter) for the given user and domain name in the
146
+   database. If a match is found and it is not set to whitelist,
147
+   false is returned. Otherwise, true is returned.
148
+   Pseudo-variables or AVPs can be used for the user, domain and
149
+   number parameters. The number and table variables are optional,
150
+   the defaults are used if they are ommited. The number parameter
151
+   can be used to check for example against the from URI user.
148 152
 
149 153
    Example 1.4. check_user_blacklist usage
150 154
 ...
... ...
@@ -123,13 +123,16 @@ modparam("userblacklist", "use_domain", 0)
123 123
 	<title>Exported Functions</title>
124 124
 	<section>
125 125
 	    <title>
126
-		<function moreinfo="none">check_user_blacklist (string user, string domain)</function>
126
+		<function moreinfo="none">check_user_blacklist (string user, string domain, string number, string table)</function>
127 127
 	    </title>
128 128
 	    <para>
129
-		Finds the longest prefix that matches the request URI for the given user
130
-		and domain name in the database. If a match is found and it is not set
131
-		to whitelist, false is returned. Otherwise, true is returned.
132
-		Pseudo-variables or AVPs can be used for both parameters.
129
+		Finds the longest prefix that matches the request URI user (or the number
130
+		parameter) for the given user and domain name in the database.
131
+		If a match is found and it is not set to whitelist, false is returned.
132
+		Otherwise, true is returned. Pseudo-variables or AVPs can be used for
133
+		the user, domain and number parameters. The number and table variables
134
+		are optional, the defaults are used if they are ommited. The number
135
+		parameter can be used to check for example against the from URI user.
133 136
 	    </para>
134 137
 	<example>
135 138
 		<title><function>check_user_blacklist</function> usage</title>
... ...
@@ -76,8 +76,9 @@ void dt_insert(struct dt_node_t *root, const char *number, char whitelist)
76 76
 	struct dt_node_t *node = root;
77 77
 
78 78
 	int i = 0;
79
+	unsigned int digit;
79 80
 	while (number[i] != 0) {
80
-		unsigned int digit = number[i] - '0';
81
+		digit = number[i] - '0';
81 82
 		if (digit > 9) {
82 83
 			LM_ERR("cannot insert non-numerical number\n");
83 84
 			return;
... ...
@@ -111,9 +112,9 @@ int dt_longest_match(struct dt_node_t *root, const char *number, char *whitelist
111 112
 		nmatch = 0;
112 113
 		*whitelist = node->whitelist;
113 114
 	}
115
+	unsigned int digit;
114 116
 	while (number[i] != 0) {
115
-		unsigned int digit = number[i] - '0';
116
-		if (digit > 9) return nmatch;
117
+		digit = number[i] - '0';
117 118
 		if (!node->child[digit]) return nmatch;
118 119
 		node = node->child[digit];
119 120
 		i++;
... ...
@@ -66,8 +66,8 @@ static int check_blacklist_fixup(void** param, int param_no);
66 66
 static int check_user_blacklist_fixup(void** param, int param_no);
67 67
 
68 68
 /* ---- exported commands: */
69
-static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2);
70
-static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1, char *unused);
69
+static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4);
70
+static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1);
71 71
 
72 72
 /* ---- module init functions: */
73 73
 static int mod_init(void);
... ...
@@ -76,11 +76,13 @@ static int mi_child_init(void);
76 76
 static void mod_destroy(void);
77 77
 
78 78
 /* --- fifo functions */
79
-struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param);  /* usage: openserctl fifo sp_reload_blacklist */
79
+struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param);  /* usage: openserctl fifo reload_blacklist */
80 80
 
81 81
 
82 82
 static cmd_export_t cmds[]={
83 83
 	{ "check_user_blacklist", (cmd_function)check_user_blacklist, 2, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
84
+	{ "check_user_blacklist", (cmd_function)check_user_blacklist, 3, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
85
+	{ "check_user_blacklist", (cmd_function)check_user_blacklist, 4, check_user_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
84 86
 	{ "check_blacklist", (cmd_function)check_blacklist, 1, check_blacklist_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE },
85 87
 	{ 0, 0, 0, 0, 0, 0}
86 88
 };
... ...
@@ -103,14 +105,14 @@ static mi_export_t mi_cmds[] = {
103 105
 
104 106
 struct module_exports exports= {
105 107
 	"userblacklist",
106
-	DEFAULT_DLFLAGS,   /* dlopen flags */
108
+	DEFAULT_DLFLAGS,
107 109
 	cmds,
108 110
 	params,
109 111
 	0,
110 112
 	mi_cmds,
111 113
 	0,
112
-	0,          /* extra processes */
113
-	mod_init,   /* module initialization function */
114
+	0,
115
+	mod_init,
114 116
 	0,
115 117
 	mod_destroy,
116 118
 	child_init
... ...
@@ -145,76 +147,126 @@ static int check_user_blacklist_fixup(void** param, int param_no)
145 147
 	s.s = (char*)*param;
146 148
 	s.len = strlen(s.s);
147 149
 
148
-	model=NULL;
149
-	if (param_no==1 || param_no==2) {
150
-		if(s.len==0) {
151
-			LM_ERR("no param %d!\n", param_no);
150
+	if (param_no > 0 && param_no <= 4) {
151
+		if(s.len == 0 && param_no != 4) {
152
+			LM_ERR("no parameter %d\n", param_no);
152 153
 			return E_UNSPEC;
153 154
 		}
154 155
 
155 156
 		if(pv_parse_format(&s, &model) < 0 || !model) {
156
-			LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
157
+			LM_ERR("wrong format [%.*s] for parameter %d\n", s.len, s.s, param_no);
157 158
 			return E_UNSPEC;
158 159
 		}
160
+
159 161
 		if(!model->spec.getf) {
160 162
 			if(param_no == 1) {
161
-			   if(str2int(&s, (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n) != 0) {
162
-					LM_ERR("wrong value [%s] for param no %d!\n", s.s, param_no);
163
+				if(str2int(&s, (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n) != 0) {
164
+					LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no);
163 165
 					return E_UNSPEC;
164
-			   }
166
+				}
167
+			} else {
168
+				if(param_no == 2 || param_no == 3) {
169
+					LM_ERR("wrong value [%.*s] for parameter %d\n", s.len, s.s, param_no);
170
+					return E_UNSPEC;
171
+				} else {
172
+					// only a string
173
+					return 0;
174
+				}
165 175
 			}
166 176
 		}
167 177
 		*param = (void*)model;
178
+	} else {
179
+		LM_ERR("wrong number of parameters\n");
168 180
 	}
169 181
 
170 182
 	return 0;
171 183
 }
172 184
 
173 185
 
174
-static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2)
186
+static int check_user_blacklist(struct sip_msg *msg, char* str1, char* str2, char* str3, char* str4)
175 187
 {
176 188
 	str user = { .len = 0, .s = NULL };
177 189
 	str domain = { .len = 0, .s = NULL};
190
+	str table = { .len = 0, .s = NULL};
191
+	str number = { .len = 0, .s = NULL};
192
+
178 193
 	char whitelist;
194
+	char *ptr;
179 195
 	char req_number[MAXNUMBERLEN+1];
180 196
 
197
+	/* user */
181 198
 	if(((pv_elem_p)str1)->spec.getf) {
182 199
 		if(pv_printf_s(msg, (pv_elem_p)str1, &user) != 0) {
183 200
 			LM_ERR("cannot print user pseudo-variable\n");
184 201
 			return -1;
185 202
 		}
186 203
 	}
187
-	if(((pv_elem_p)str2)->spec.getf)
188
-	{
204
+	/* domain */
205
+	if(((pv_elem_p)str2)->spec.getf) {
189 206
 		if(pv_printf_s(msg, (pv_elem_p)str2, &domain) != 0) {
190 207
 			LM_ERR("cannot print domain pseudo-variable\n");
191 208
 			return -1;
192 209
 		}
193 210
 	}
211
+	/* source number */
212
+	if(str3 != NULL && ((pv_elem_p)str3)->spec.getf) {
213
+		if(pv_printf_s(msg, (pv_elem_p)str3, &number) != 0) {
214
+			LM_ERR("cannot print number pseudo-variable\n");
215
+			return -1;
216
+		}
217
+	}
218
+	/* table name */
219
+	if(str4 != NULL && strlen(str4) > 0) {
220
+		/* string */
221
+		table.s=str4;
222
+		table.len=strlen(str4);
223
+	} else {
224
+		/* use default table name */
225
+		table.len=db_table.len;
226
+		table.s=db_table.s;
227
+	}
228
+
194 229
 	if (msg->first_line.type != SIP_REQUEST) {
195 230
 		LM_ERR("SIP msg is not a request\n");
196 231
 		return -1;
197 232
 	}
198
-	if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s) || (msg->parsed_uri.user.len > MAXNUMBERLEN)) {
199
-		LM_ERR("cannot parse msg URI\n");
200
-		return -1;
233
+
234
+	if(number.s == NULL) {
235
+		/* use R-URI */
236
+		if ((parse_sip_msg_uri(msg) < 0) || (!msg->parsed_uri.user.s) || (msg->parsed_uri.user.len > MAXNUMBERLEN)) {
237
+			LM_ERR("cannot parse msg URI\n");
238
+			return -1;
239
+		}
240
+		strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
241
+		req_number[msg->parsed_uri.user.len] = '\0';
242
+	} else {
243
+		if (number.len > MAXNUMBERLEN) {
244
+			LM_ERR("number to long\n");
245
+			return -1;
246
+		}
247
+		strncpy(req_number, number.s, number.len);
248
+		req_number[number.len] = '\0';
201 249
 	}
202
-	strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
203
-	req_number[msg->parsed_uri.user.len] = '\0';
204 250
 
205
-	LM_DBG("check entry %s\n", req_number);
206
-	if (db_build_userbl_tree(&user, &domain, &db_table, dt_root, use_domain) < 0) {
251
+	LM_DBG("check entry %s for user %.*s on domain %.*s in table %.*s\n", req_number,
252
+		user.len, user.s, domain.len, domain.s, table.len, table.s);
253
+	if (db_build_userbl_tree(&user, &domain, &table, dt_root, use_domain) < 0) {
207 254
 		LM_ERR("cannot build d-tree\n");
208 255
 		return -1;
209 256
 	}
210 257
 
211
-	if (dt_longest_match(dt_root, req_number, &whitelist) >= 0) {
258
+	ptr = req_number;
259
+	/* Skip over non-digits.  */
260
+	while (strlen(ptr) > 0 && !isdigit(*ptr)) {
261
+		ptr = ptr + 1;
262
+	}
263
+
264
+	if (dt_longest_match(dt_root, ptr, &whitelist) >= 0) {
212 265
 		if (whitelist) {
213 266
 			/* LM_ERR("whitelisted"); */
214 267
 			return 1; /* found, but is whitelisted */
215 268
 		}
216
-	}
217
-	else {
269
+	} else {
218 270
 		/* LM_ERR("not found"); */
219 271
 		return 1; /* not found is ok */
220 272
 	}
... ...
@@ -283,12 +335,12 @@ static int check_blacklist_fixup(void **arg, int arg_no)
283 335
 	char *table = (char *)(*arg);
284 336
 	struct dt_node_t *node = NULL;
285 337
 	if (arg_no != 1) {
286
-		LM_ERR("fixup with funny arg_no param.\n");
338
+		LM_ERR("wrong number of parameters\n");
287 339
 		return -1;
288 340
 	}
289 341
 
290 342
 	if (!table) {
291
-		LM_ERR("no table.\n");
343
+		LM_ERR("no table name\n");
292 344
 		return -1;
293 345
 	}
294 346
 	/* try to add the table */
... ...
@@ -300,13 +352,13 @@ static int check_blacklist_fixup(void **arg, int arg_no)
300 352
 	/* get the node that belongs to the table */
301 353
 	node = table2dt(table);
302 354
 	if (!node) {
303
-		LM_ERR("invalid table '%s'.\n", table);
355
+		LM_ERR("invalid table '%s'\n", table);
304 356
 		return -1;
305 357
 	}
306 358
 
307 359
 	struct check_blacklist_fs_t *new_arg = (struct check_blacklist_fs_t*)pkg_malloc(sizeof(struct check_blacklist_fs_t));
308 360
 	if (!new_arg) {
309
-		LM_ERR("out of private memory.\n");
361
+		LM_ERR("out of private memory\n");
310 362
 		return -1;
311 363
 	}
312 364
 	memset(new_arg, 0, sizeof(struct check_blacklist_fs_t));
... ...
@@ -317,9 +369,10 @@ static int check_blacklist_fixup(void **arg, int arg_no)
317 369
 }
318 370
 
319 371
 
320
-static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1, char *unused)
372
+static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg1)
321 373
 {
322 374
 	char whitelist;
375
+	char *ptr;
323 376
 	char req_number[MAXNUMBERLEN+1];
324 377
 
325 378
 	if (msg->first_line.type != SIP_REQUEST) {
... ...
@@ -339,8 +392,14 @@ static int check_blacklist(struct sip_msg *msg, struct check_blacklist_fs_t *arg
339 392
 	strncpy(req_number, msg->parsed_uri.user.s, msg->parsed_uri.user.len);
340 393
 	req_number[msg->parsed_uri.user.len] = '\0';
341 394
 
395
+	ptr = req_number;
396
+	/* Skip over non-digits.  */
397
+	while (strlen(ptr) > 0 && !isdigit(*ptr)) {
398
+		ptr = ptr + 1;
399
+	}
400
+
342 401
 	LM_DBG("check entry %s\n", req_number);
343
-	if (dt_longest_match(arg1->dt_root, req_number, &whitelist) >= 0) {
402
+	if (dt_longest_match(arg1->dt_root, ptr, &whitelist) >= 0) {
344 403
 		if (whitelist) {
345 404
 			/* LM_DBG("whitelisted"); */
346 405
 			return 1; /* found, but is whitelisted */
... ...
@@ -374,11 +433,11 @@ static int reload_sources(void)
374 433
 		tmp.len = strlen(src->table);
375 434
 		int n = db_reload_source(&tmp, src->dt_root);
376 435
 		if (n < 0) {
377
-			LM_ERR("cannot reload source from '%.*s'.\n", tmp.len, tmp.s);
436
+			LM_ERR("cannot reload source from '%.*s'\n", tmp.len, tmp.s);
378 437
 			result = -1;
379 438
 			break;
380 439
 		}
381
-		LM_INFO("got %d entries from '%.*s'.\n", n, tmp.len, tmp.s);
440
+		LM_INFO("got %d entries from '%.*s'\n", n, tmp.len, tmp.s);
382 441
 		src = src->next;
383 442
 	}
384 443
 
... ...
@@ -393,7 +452,7 @@ static int init_source_list(void)
393 452
 {
394 453
 	sources = shm_malloc(sizeof(struct source_list_t));
395 454
 	if (!sources) {
396
-		LM_ERR("out of private memory.\n");
455
+		LM_ERR("out of private memory\n");
397 456
 		return -1;
398 457
 	}
399 458
 	sources->head = NULL;
... ...
@@ -461,15 +520,14 @@ struct mi_root * mi_reload_blacklist(struct mi_root* cmd, void* param)
461 520
 
462 521
 static int mod_init(void)
463 522
 {
464
-	LM_INFO("initializing");
523
+	LM_INFO("initializing ...\n");
465 524
 	db_url.len = strlen(db_url.s);
466 525
 	db_table.len = strlen(db_table.s);
467 526
 
468
-	/* FIXME check table version is missing */
469 527
 	if (db_bind(&db_url) != 0) return -1;
470 528
 	if (init_shmlock() != 0) return -1;
471 529
 	if (init_source_list() != 0) return -1;
472
-	LM_INFO("finished initializing");
530
+	LM_INFO("finished initializing\n");
473 531
 
474 532
 	return 0;
475 533
 }