Browse code

- support for AVP classes (user, domain, global attributes)

Jan Janak authored on 17/11/2005 11:59:27
Showing 3 changed files
... ...
@@ -228,7 +228,7 @@ end:
228 228
 	skipped = 0;
229 229
 #endif
230 230
 	/* free possible loaded avps -bogdan */
231
-	reset_avps();
231
+	reset_user_avps();
232 232
 	DBG("receive_msg: cleaning up\n");
233 233
 	free_sip_msg(msg);
234 234
 	pkg_free(msg);
... ...
@@ -239,14 +239,14 @@ end:
239 239
 error_rpl:
240 240
 	/* execute post reply-script callbacks */
241 241
 	exec_post_rpl_cb(msg);
242
-	reset_avps();
242
+	reset_user_avps();
243 243
 	goto error02;
244 244
 error_req:
245 245
 	DBG("receive_msg: error:...\n");
246 246
 	/* execute post request-script callbacks */
247 247
 	exec_post_req_cb(msg);
248 248
 	/* free possible loaded avps -bogdan */
249
-	reset_avps();
249
+	reset_user_avps();
250 250
 error02:
251 251
 	free_sip_msg(msg);
252 252
 	pkg_free(msg);
... ...
@@ -60,10 +60,15 @@ struct avp_galias {
60 60
 };
61 61
 
62 62
 static struct avp_galias *galiases = 0;
63
-static struct usr_avp *global_avps = 0;
64
-static struct usr_avp **crt_avps  = &global_avps;
65 63
 
66
-static regex_t* search_re;  /* Regex for use in subsequent searches */
64
+static avp_t *global_avps = 0;  /* Global attribute list */
65
+static avp_t *domain_avps = 0;  /* Domain-specific attribute list */
66
+static avp_t *user_avps = 0;    /* User-specific attribute list */
67
+
68
+static avp_t **crt_global_avps = &global_avps; /* Pointer to the current list of global attributes */
69
+static avp_t **crt_domain_avps = &domain_avps; /* Pointer to the current list of domain attributes */
70
+static avp_t **crt_user_avps   = &user_avps;   /* Pointer to the current list of user attributes */
71
+
67 72
 
68 73
 inline static unsigned short compute_ID( str *name )
69 74
 {
... ...
@@ -79,13 +84,33 @@ inline static unsigned short compute_ID( str *name )
79 79
 
80 80
 int add_avp(unsigned short flags, int_str name, int_str val)
81 81
 {
82
-	struct usr_avp *avp;
82
+	avp_t **list;
83
+	avp_t *avp;
83 84
 	str *s;
84 85
 	struct str_int_data *sid;
85 86
 	struct str_str_data *ssd;
87
+	unsigned short avp_class;
86 88
 	int len;
87 89
 
88
-	assert( crt_avps!=0 );
90
+	if ((flags & ALL_AVP_CLASSES) == 0) {
91
+		     /* The caller did not specify any class to search in, so enable
92
+		      * all of them by default
93
+		      */
94
+		flags |= ALL_AVP_CLASSES;
95
+	}
96
+
97
+	if (IS_USER_AVP(flags)) {
98
+		list = crt_user_avps;
99
+		avp_class = AVP_USER;
100
+	} else if (IS_DOMAIN_AVP(flags)) {
101
+		list = crt_domain_avps;
102
+		avp_class = AVP_DOMAIN;
103
+	} else {
104
+		list = crt_global_avps;
105
+		avp_class = AVP_GLOBAL;
106
+	}
107
+
108
+	assert(list != 0);
89 109
 
90 110
 	if ( name.s==0 ) {
91 111
 		LOG(L_ERR,"ERROR:avp:add_avp: 0 ID or NULL NAME AVP!");
... ...
@@ -117,11 +142,14 @@ int add_avp(unsigned short flags, int_str name, int_str val)
117 117
 		goto error;
118 118
 	}
119 119
 
120
-	avp->flags = flags;
120
+		 /* Make that only the selected class is set
121
+		  * if the caller set more classes in flags
122
+		  */
123
+	avp->flags = flags & (~(ALL_AVP_CLASSES) | avp_class);
121 124
 	avp->id = (flags&AVP_NAME_STR)? compute_ID(name.s) : name.n ;
122 125
 
123
-	avp->next = *crt_avps;
124
-	*crt_avps = avp;
126
+	avp->next = *list;
127
+	*list = avp;
125 128
 
126 129
 	switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
127 130
 	{
... ...
@@ -167,8 +195,7 @@ error:
167 167
 
168 168
 
169 169
 /* get value functions */
170
-
171
-inline str* get_avp_name(struct usr_avp *avp)
170
+inline str* get_avp_name(avp_t *avp)
172 171
 {
173 172
 	switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
174 173
 	{
... ...
@@ -191,7 +218,7 @@ inline str* get_avp_name(struct usr_avp *avp)
191 191
 }
192 192
 
193 193
 
194
-inline void get_avp_val(struct usr_avp *avp, int_str *val)
194
+inline void get_avp_val(avp_t *avp, int_str *val)
195 195
 {
196 196
 	if (avp==0 || val==0)
197 197
 		return;
... ...
@@ -217,140 +244,157 @@ inline void get_avp_val(struct usr_avp *avp, int_str *val)
217 217
 }
218 218
 
219 219
 
220
-struct usr_avp** get_avp_list( )
220
+/* Return the current list of user attributes */
221
+avp_t** get_user_avp_list(void)
221 222
 {
222
-	assert( crt_avps!=0 );
223
-	return crt_avps;
223
+	assert(crt_user_avps != 0);
224
+	return crt_user_avps;
224 225
 }
225 226
 
227
+/* Return the current list of domain attributes */
228
+avp_t** get_domain_avp_list(void)
229
+{
230
+	assert(crt_domain_avps != 0);
231
+	return crt_domain_avps;
232
+}
226 233
 
227 234
 
235
+/* Return the current list of domain attributes */
236
+avp_t** get_global_avp_list(void)
237
+{
238
+	assert(crt_global_avps != 0);
239
+	return crt_global_avps;
240
+}
228 241
 
229
-/* search functions */
230 242
 
231
-inline static struct usr_avp *internal_search_ID_avp( struct usr_avp *avp,
232
-												unsigned short id)
243
+/*
244
+ * Compare given id with id in avp, return true if they match
245
+ */
246
+static inline int match_by_id(avp_t* avp, unsigned short id)
233 247
 {
234
-	for( ; avp ; avp=avp->next ) {
235
-		if ( id==avp->id && (avp->flags&AVP_NAME_STR)==0  ) {
236
-			return avp;
237
-		}
248
+	if (avp->id == id && (avp->flags&AVP_NAME_STR)==0) {
249
+		return 1;
238 250
 	}
239 251
 	return 0;
240 252
 }
241 253
 
242 254
 
243
-
244
-inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
245
-												unsigned short id, str *name)
255
+/*
256
+ * Compare given name with name in avp, return true if they are same
257
+ */
258
+static inline int match_by_name(avp_t* avp, unsigned short id, str* name)
246 259
 {
247
-	str * avp_name;
248
-
249
-	for( ; avp ; avp=avp->next )
250
-		if ( id==avp->id && avp->flags&AVP_NAME_STR &&
251
-		(avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
252
-		 && !strncasecmp( avp_name->s, name->s, name->len) ) {
253
-			return avp;
254
-		}
260
+	str* avp_name;
261
+	if (id==avp->id && avp->flags&AVP_NAME_STR &&
262
+	    (avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
263
+	    && !strncasecmp( avp_name->s, name->s, name->len) ) {
264
+		return 1;
265
+	}
255 266
 	return 0;
256 267
 }
257 268
 
258 269
 
259
-/* find an attribute by name match against regular expression */
260
-static struct usr_avp *internal_search_avp_by_re(struct usr_avp *avp, regex_t* re)
270
+/*
271
+ * Compare name with name in AVP using regular expressions, return
272
+ * true if they match
273
+ */
274
+static inline int match_by_re(avp_t* avp, regex_t* re)
261 275
 {
262
-	str * avp_name;
263 276
 	regmatch_t pmatch;
264
-	
265
-	     /* validation */
266
-	if (re==0) {
267
-		LOG(L_ERR, "ERROR: internal_search_avp_by_re: No regular expression\n");
277
+	str * avp_name;
278
+	     /* AVP identifiable by name ? */
279
+	if (!(avp->flags&AVP_NAME_STR)) return 0;
280
+	if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
268 281
 		return 0;
269
-	}
270
-	
271
-	for( ; avp ; avp=avp->next ) {
272
-		     /* AVP identifiable by name ? */
273
-		if (!(avp->flags&AVP_NAME_STR)) continue;
274
-		if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
275
-			continue;
276
-		if (!avp_name->s) /* AVP name validation */
277
-			continue;
278
-		if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
279
-			avp->search_type|= AVP_NAME_RE;
280
-			return avp;
281
-		}
282
+	if (!avp_name->s) /* AVP name validation */
283
+		return 0;
284
+	if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
285
+		return 1;
282 286
 	}
283 287
 	return 0;
284 288
 }
285 289
 
286 290
 
287
-struct usr_avp *search_first_avp( unsigned short name_type,
288
-				  int_str name, int_str *val)
291
+avp_t *search_first_avp(unsigned short flags, int_str name, int_str *val, struct search_state* s)
289 292
 {
290
-	struct usr_avp *avp;
293
+	static struct search_state st;
291 294
 
292
-	assert( crt_avps!=0 );
293
-	
294
-	if (*crt_avps==0)
295
-		return 0;
295
+	assert( crt_user_avps != 0 );
296
+	assert( crt_domain_avps != 0);
297
+	assert( crt_global_avps != 0);
296 298
 
297
-	if ( name.s==0) {
299
+	if (name.s==0) {
298 300
 		LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
299 301
 		return 0;
300 302
 	}
301 303
 
302
-	/* search for the AVP by ID (&name) */
303
-	if (name_type&AVP_NAME_STR) {
304
-		if ( name.s->s==0 || name.s->len==0) {
305
-			LOG(L_ERR,"ERROR:avp:search_first_avp: EMPTY NAME AVP!");
306
-			return 0;
307
-		}
308
-		avp = internal_search_name_avp(*crt_avps,compute_ID(name.s),name.s);
309
-	} else if (name_type & AVP_NAME_RE) {
310
-		search_re = name.re;
311
-		avp = internal_search_avp_by_re(*crt_avps, search_re);
304
+	if (!s) s = &st;
305
+
306
+	if ((flags & ALL_AVP_CLASSES) == 0) {
307
+		     /* The caller did not specify any class to search in, so enable
308
+		      * all of them by default
309
+		      */
310
+		flags |= ALL_AVP_CLASSES;
311
+	}
312
+	s->flags = flags;
313
+	if (IS_USER_AVP(flags)) {
314
+		s->avp = *crt_user_avps;
315
+	} else if (IS_DOMAIN_AVP(flags)) {
316
+		s->avp = *crt_domain_avps;
312 317
 	} else {
313
-		avp = internal_search_ID_avp( *crt_avps, name.n );
318
+		s->avp = *crt_global_avps;
314 319
 	}
315
-	
316
-	if (avp) {
317
-		     /* remember type of search for next searches */
318
-		avp->search_type=name_type;
319
-		if (val) /* get the value - if required */
320
-			get_avp_val(avp, val);
320
+	s->name = name;
321
+
322
+	if (!(flags & AVP_NAME_STR) && !(flags & AVP_NAME_RE)) {
323
+		s->id = compute_ID(name.s);
321 324
 	}
322
-	
323
-	return avp;
325
+
326
+	return search_next_avp(s, val);
324 327
 }
325 328
 
326 329
 
327 330
 
328
-struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
331
+avp_t *search_next_avp(struct search_state* s, int_str *val )
329 332
 {
330
-	struct usr_avp* next;
333
+	avp_t* avp;
334
+	int matched;
331 335
 
332
-	if (avp == 0) {
336
+	if (s == 0) {
337
+		LOG(L_ERR, "search_next:avp: Invalid parameter value\n");
333 338
 		return 0;
334 339
 	}
335 340
 
336
-	next = avp->next;
337
-	if (next == 0) {
338
-		return 0;
339
-	}
341
+	while(1) {
342
+		for( ; s->avp; s->avp = s->avp->next) {
343
+			if (s->flags & AVP_NAME_RE) {
344
+				matched = match_by_re(s->avp, s->name.re);
345
+			} else if (s->flags & AVP_NAME_STR) {
346
+				matched = match_by_name(s->avp, s->id, s->name.s);
347
+			} else {
348
+				matched = match_by_id(s->avp, s->name.n);
349
+			}
350
+			if (matched) {
351
+				avp = s->avp;
352
+				s->avp = s->avp->next;
353
+				if (val) get_avp_val(avp, val);
354
+				return avp;
355
+			}
356
+		}
340 357
 
341
-	if (avp->search_type & AVP_NAME_RE) {
342
-		next = internal_search_avp_by_re(next, search_re);
343
-	} else if (avp->flags & AVP_NAME_STR) {
344
-		next = internal_search_name_avp(next, avp->id, get_avp_name(avp));
345
-	} else {
346
-		next = internal_search_ID_avp(next, avp->id);
358
+		if (IS_USER_AVP(s->flags)) {
359
+			s->flags &= ~AVP_USER;
360
+			s->avp = *crt_domain_avps;
361
+		} else if (IS_DOMAIN_AVP(s->flags)) {
362
+			s->flags &= ~AVP_DOMAIN;
363
+			s->avp = *crt_global_avps;
364
+		} else {
365
+			s->flags &= ~AVP_GLOBAL;
366
+			return 0;
367
+		}
347 368
 	}
348 369
 
349
-	if (next && val) {
350
-		get_avp_val(next, val);
351
-	}
352
-	
353
-	return next;
370
+	return 0;
354 371
 }
355 372
 
356 373
 
... ...
@@ -358,17 +402,16 @@ struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
358 358
 
359 359
 /********* free functions ********/
360 360
 
361
-void destroy_avp( struct usr_avp *avp_del)
361
+void destroy_avp( avp_t *avp_del)
362 362
 {
363
-	struct usr_avp *avp;
364
-	struct usr_avp *avp_prev;
363
+	avp_t *avp, *avp_prev;
365 364
 
366
-	for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
365
+	for( avp_prev=0,avp=*crt_user_avps ; avp ; avp_prev=avp,avp=avp->next ) {
367 366
 		if (avp==avp_del) {
368 367
 			if (avp_prev)
369 368
 				avp_prev->next=avp->next;
370 369
 			else
371
-				*crt_avps = avp->next;
370
+				*crt_user_avps = avp->next;
372 371
 			shm_free(avp);
373 372
 			return;
374 373
 		}
... ...
@@ -376,9 +419,9 @@ void destroy_avp( struct usr_avp *avp_del)
376 376
 }
377 377
 
378 378
 
379
-void destroy_avp_list_unsafe( struct usr_avp **list )
379
+void destroy_avp_list_unsafe( avp_t **list )
380 380
 {
381
-	struct usr_avp *avp, *foo;
381
+	avp_t *avp, *foo;
382 382
 
383 383
 	avp = *list;
384 384
 	while( avp ) {
... ...
@@ -390,9 +433,9 @@ void destroy_avp_list_unsafe( struct usr_avp **list )
390 390
 }
391 391
 
392 392
 
393
-inline void destroy_avp_list( struct usr_avp **list )
393
+inline void destroy_avp_list( avp_t **list )
394 394
 {
395
-	struct usr_avp *avp, *foo;
395
+	avp_t *avp, *foo;
396 396
 
397 397
 	DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
398 398
 	avp = *list;
... ...
@@ -405,29 +448,50 @@ inline void destroy_avp_list( struct usr_avp **list )
405 405
 }
406 406
 
407 407
 
408
-void reset_avps( )
408
+void reset_user_avps(void)
409 409
 {
410
-	assert( crt_avps!=0 );
410
+	assert( crt_user_avps!=0 );
411 411
 	
412
-	if ( crt_avps!=&global_avps) {
413
-		crt_avps = &global_avps;
412
+	if ( crt_user_avps!=&user_avps) {
413
+		crt_user_avps = &user_avps;
414 414
 	}
415
-	destroy_avp_list( crt_avps );
415
+	destroy_avp_list( crt_user_avps );
416 416
 }
417 417
 
418 418
 
419
-struct usr_avp** set_avp_list( struct usr_avp **list )
419
+avp_t** set_user_avp_list( avp_t **list )
420 420
 {
421
-	struct usr_avp **foo;
422
-	
423
-	assert( crt_avps!=0 );
421
+	avp_t **foo;
424 422
 
425
-	foo = crt_avps;
426
-	crt_avps = list;
423
+	assert( crt_user_avps!=0 );
424
+
425
+	foo = crt_user_avps;
426
+	crt_user_avps = list;
427 427
 	return foo;
428 428
 }
429 429
 
430 430
 
431
+avp_t** set_domain_avp_list( avp_t **list )
432
+{
433
+	avp_t **foo;
434
+
435
+	assert( crt_domain_avps!=0 );
436
+
437
+	foo = crt_domain_avps;
438
+	crt_domain_avps = list;
439
+	return foo;
440
+}
441
+
442
+avp_t** set_global_avp_list( avp_t **list )
443
+{
444
+	avp_t **foo;
445
+
446
+	assert( crt_global_avps!=0 );
447
+
448
+	foo = crt_global_avps;
449
+	crt_global_avps = list;
450
+	return foo;
451
+}
431 452
 
432 453
 
433 454
 /********* global aliases functions ********/
... ...
@@ -673,5 +737,3 @@ parse_error:
673 673
 error:
674 674
 	return -1;
675 675
 }
676
-
677
-
... ...
@@ -44,13 +44,18 @@
44 44
  *   -------------------------------------------------------
45 45
  *     0        avp_core          avp has a string name
46 46
  *     1        avp_core          avp has a string value
47
+ *     2        avp_core          regex search in progress
47 48
  *     3        avpops module     avp was loaded from DB
48 49
  *     4        lcr module        contact avp qvalue change
50
+ *     5        core              avp is in user list
51
+ *     6        core              avp is in domain list
52
+ *     7        core              avp is in global list
49 53
  *
50 54
  */
51 55
 
52 56
 #include "str.h"
53 57
 
58
+
54 59
 struct str_int_data {
55 60
 	str name;
56 61
 	int val;
... ...
@@ -68,42 +73,74 @@ typedef union {
68 68
 } int_str;
69 69
 
70 70
 
71
-struct usr_avp {
71
+typedef struct usr_avp {
72 72
 	unsigned short id;
73 73
 	     /* Flags that are kept for the AVP lifetime */
74 74
 	unsigned short flags;
75
-	     /* Type of search in progress */
76
-	unsigned short search_type;
77 75
 	struct usr_avp *next;
78 76
 	void *data;
77
+} avp_t;
78
+
79
+
80
+/*
81
+ * AVP search state
82
+ */
83
+struct search_state {
84
+	unsigned short flags;  /* Type of search and additional flags */
85
+	unsigned short id;
86
+	int_str name;
87
+	avp_t* avp;            /* Current AVP */
88
+	regex_t* search_re;    /* Compiled regular expression */
79 89
 };
80 90
 
81 91
 
82 92
 #define AVP_NAME_STR     (1<<0)
83 93
 #define AVP_VAL_STR      (1<<1)
84 94
 #define AVP_NAME_RE      (1<<2)
95
+#define AVP_USER         (1<<5)
96
+#define AVP_DOMAIN       (1<<6)
97
+#define AVP_GLOBAL       (1<<7)
98
+
99
+#define ALL_AVP_CLASSES (AVP_USER|AVP_DOMAIN|AVP_GLOBAL)
100
+
101
+/* True for user avps */
102
+#define IS_USER_AVP(flags) ((flags) & AVP_USER)
103
+
104
+/* True for domain avps */
105
+#define IS_DOMAIN_AVP(flags) ((flags) & AVP_DOMAIN)
106
+
107
+/* true for global avps */
108
+#define IS_GLOBAL_AVP(flags) ((flags) & AVP_GLOBAL)
85 109
 
86 110
 #define GALIAS_CHAR_MARKER  '$'
87 111
 
88 112
 /* add functions */
89
-int add_avp( unsigned short flags, int_str name, int_str val);
113
+int add_avp(unsigned short flags, int_str name, int_str val);
90 114
 
91 115
 /* search functions */
92
-struct usr_avp *search_first_avp( unsigned short name_type, int_str name,
93
-															int_str *val );
94
-struct usr_avp *search_next_avp( struct usr_avp *avp, int_str *val  );
116
+avp_t *search_first_avp( unsigned short flags, int_str name,
117
+			 int_str *val, struct search_state* state);
118
+avp_t *search_next_avp(struct search_state* state, int_str *val);
95 119
 
96 120
 /* free functions */
97
-void reset_avps( );
98
-void destroy_avp( struct usr_avp *avp);
99
-void destroy_avp_list( struct usr_avp **list );
100
-void destroy_avp_list_unsafe( struct usr_avp **list );
121
+void reset_user_avps(void);
122
+
123
+void destroy_avp(avp_t *avp);
124
+void destroy_avp_list(avp_t **list );
125
+void destroy_avp_list_unsafe(avp_t **list );
101 126
 
102 127
 /* get func */
103
-void get_avp_val(struct usr_avp *avp, int_str *val );
104
-str* get_avp_name(struct usr_avp *avp);
105
-struct usr_avp** set_avp_list( struct usr_avp **list );
106
-struct usr_avp** get_avp_list( );
128
+void get_avp_val(avp_t *avp, int_str *val );
129
+str* get_avp_name(avp_t *avp);
130
+
131
+avp_t** get_user_avp_list(void);   /* Return current list of user avps */
132
+avp_t** get_domain_avp_list(void); /* Return current list of domain avps */
133
+avp_t** get_global_avp_list(void); /* Return current list of global avps */
134
+
135
+avp_t** set_user_avp_list(avp_t **list);   /* Set current list of user avps to list */
136
+avp_t** set_domain_avp_list(avp_t **list); /* Set current list of domain avps to list */
137
+avp_t** set_global_avp_list(avp_t **list); /* Set current list of global avps to list */
138
+
107 139
 
108 140
 /* global alias functions (manipulation and parsing)*/
109 141
 int add_avp_galias_str(char *alias_definition);