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 84
 
80 85
 int add_avp(unsigned short flags, int_str name, int_str val)
81 86
 {
82
-	struct usr_avp *avp;
87
+	avp_t **list;
88
+	avp_t *avp;
83 89
 	str *s;
84 90
 	struct str_int_data *sid;
85 91
 	struct str_str_data *ssd;
92
+	unsigned short avp_class;
86 93
 	int len;
87 94
 
88
-	assert( crt_avps!=0 );
95
+	if ((flags & ALL_AVP_CLASSES) == 0) {
96
+		     /* The caller did not specify any class to search in, so enable
97
+		      * all of them by default
98
+		      */
99
+		flags |= ALL_AVP_CLASSES;
100
+	}
101
+
102
+	if (IS_USER_AVP(flags)) {
103
+		list = crt_user_avps;
104
+		avp_class = AVP_USER;
105
+	} else if (IS_DOMAIN_AVP(flags)) {
106
+		list = crt_domain_avps;
107
+		avp_class = AVP_DOMAIN;
108
+	} else {
109
+		list = crt_global_avps;
110
+		avp_class = AVP_GLOBAL;
111
+	}
112
+
113
+	assert(list != 0);
89 114
 
90 115
 	if ( name.s==0 ) {
91 116
 		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 142
 		goto error;
118 143
 	}
119 144
 
120
-	avp->flags = flags;
145
+		 /* Make that only the selected class is set
146
+		  * if the caller set more classes in flags
147
+		  */
148
+	avp->flags = flags & (~(ALL_AVP_CLASSES) | avp_class);
121 149
 	avp->id = (flags&AVP_NAME_STR)? compute_ID(name.s) : name.n ;
122 150
 
123
-	avp->next = *crt_avps;
124
-	*crt_avps = avp;
151
+	avp->next = *list;
152
+	*list = avp;
125 153
 
126 154
 	switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
127 155
 	{
... ...
@@ -167,8 +195,7 @@ error:
167 195
 
168 196
 
169 197
 /* get value functions */
170
-
171
-inline str* get_avp_name(struct usr_avp *avp)
198
+inline str* get_avp_name(avp_t *avp)
172 199
 {
173 200
 	switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
174 201
 	{
... ...
@@ -191,7 +218,7 @@ inline str* get_avp_name(struct usr_avp *avp)
191 218
 }
192 219
 
193 220
 
194
-inline void get_avp_val(struct usr_avp *avp, int_str *val)
221
+inline void get_avp_val(avp_t *avp, int_str *val)
195 222
 {
196 223
 	if (avp==0 || val==0)
197 224
 		return;
... ...
@@ -217,140 +244,157 @@ inline void get_avp_val(struct usr_avp *avp, int_str *val)
217 244
 }
218 245
 
219 246
 
220
-struct usr_avp** get_avp_list( )
247
+/* Return the current list of user attributes */
248
+avp_t** get_user_avp_list(void)
221 249
 {
222
-	assert( crt_avps!=0 );
223
-	return crt_avps;
250
+	assert(crt_user_avps != 0);
251
+	return crt_user_avps;
224 252
 }
225 253
 
254
+/* Return the current list of domain attributes */
255
+avp_t** get_domain_avp_list(void)
256
+{
257
+	assert(crt_domain_avps != 0);
258
+	return crt_domain_avps;
259
+}
226 260
 
227 261
 
262
+/* Return the current list of domain attributes */
263
+avp_t** get_global_avp_list(void)
264
+{
265
+	assert(crt_global_avps != 0);
266
+	return crt_global_avps;
267
+}
228 268
 
229
-/* search functions */
230 269
 
231
-inline static struct usr_avp *internal_search_ID_avp( struct usr_avp *avp,
232
-												unsigned short id)
270
+/*
271
+ * Compare given id with id in avp, return true if they match
272
+ */
273
+static inline int match_by_id(avp_t* avp, unsigned short id)
233 274
 {
234
-	for( ; avp ; avp=avp->next ) {
235
-		if ( id==avp->id && (avp->flags&AVP_NAME_STR)==0  ) {
236
-			return avp;
237
-		}
275
+	if (avp->id == id && (avp->flags&AVP_NAME_STR)==0) {
276
+		return 1;
238 277
 	}
239 278
 	return 0;
240 279
 }
241 280
 
242 281
 
243
-
244
-inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
245
-												unsigned short id, str *name)
282
+/*
283
+ * Compare given name with name in avp, return true if they are same
284
+ */
285
+static inline int match_by_name(avp_t* avp, unsigned short id, str* name)
246 286
 {
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
-		}
287
+	str* avp_name;
288
+	if (id==avp->id && avp->flags&AVP_NAME_STR &&
289
+	    (avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
290
+	    && !strncasecmp( avp_name->s, name->s, name->len) ) {
291
+		return 1;
292
+	}
255 293
 	return 0;
256 294
 }
257 295
 
258 296
 
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)
297
+/*
298
+ * Compare name with name in AVP using regular expressions, return
299
+ * true if they match
300
+ */
301
+static inline int match_by_re(avp_t* avp, regex_t* re)
261 302
 {
262
-	str * avp_name;
263 303
 	regmatch_t pmatch;
264
-	
265
-	     /* validation */
266
-	if (re==0) {
267
-		LOG(L_ERR, "ERROR: internal_search_avp_by_re: No regular expression\n");
304
+	str * avp_name;
305
+	     /* AVP identifiable by name ? */
306
+	if (!(avp->flags&AVP_NAME_STR)) return 0;
307
+	if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
268 308
 		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
-		}
309
+	if (!avp_name->s) /* AVP name validation */
310
+		return 0;
311
+	if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
312
+		return 1;
282 313
 	}
283 314
 	return 0;
284 315
 }
285 316
 
286 317
 
287
-struct usr_avp *search_first_avp( unsigned short name_type,
288
-				  int_str name, int_str *val)
318
+avp_t *search_first_avp(unsigned short flags, int_str name, int_str *val, struct search_state* s)
289 319
 {
290
-	struct usr_avp *avp;
320
+	static struct search_state st;
291 321
 
292
-	assert( crt_avps!=0 );
293
-	
294
-	if (*crt_avps==0)
295
-		return 0;
322
+	assert( crt_user_avps != 0 );
323
+	assert( crt_domain_avps != 0);
324
+	assert( crt_global_avps != 0);
296 325
 
297
-	if ( name.s==0) {
326
+	if (name.s==0) {
298 327
 		LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
299 328
 		return 0;
300 329
 	}
301 330
 
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);
331
+	if (!s) s = &st;
332
+
333
+	if ((flags & ALL_AVP_CLASSES) == 0) {
334
+		     /* The caller did not specify any class to search in, so enable
335
+		      * all of them by default
336
+		      */
337
+		flags |= ALL_AVP_CLASSES;
338
+	}
339
+	s->flags = flags;
340
+	if (IS_USER_AVP(flags)) {
341
+		s->avp = *crt_user_avps;
342
+	} else if (IS_DOMAIN_AVP(flags)) {
343
+		s->avp = *crt_domain_avps;
312 344
 	} else {
313
-		avp = internal_search_ID_avp( *crt_avps, name.n );
345
+		s->avp = *crt_global_avps;
314 346
 	}
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);
347
+	s->name = name;
348
+
349
+	if (!(flags & AVP_NAME_STR) && !(flags & AVP_NAME_RE)) {
350
+		s->id = compute_ID(name.s);
321 351
 	}
322
-	
323
-	return avp;
352
+
353
+	return search_next_avp(s, val);
324 354
 }
325 355
 
326 356
 
327 357
 
328
-struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
358
+avp_t *search_next_avp(struct search_state* s, int_str *val )
329 359
 {
330
-	struct usr_avp* next;
360
+	avp_t* avp;
361
+	int matched;
331 362
 
332
-	if (avp == 0) {
363
+	if (s == 0) {
364
+		LOG(L_ERR, "search_next:avp: Invalid parameter value\n");
333 365
 		return 0;
334 366
 	}
335 367
 
336
-	next = avp->next;
337
-	if (next == 0) {
338
-		return 0;
339
-	}
368
+	while(1) {
369
+		for( ; s->avp; s->avp = s->avp->next) {
370
+			if (s->flags & AVP_NAME_RE) {
371
+				matched = match_by_re(s->avp, s->name.re);
372
+			} else if (s->flags & AVP_NAME_STR) {
373
+				matched = match_by_name(s->avp, s->id, s->name.s);
374
+			} else {
375
+				matched = match_by_id(s->avp, s->name.n);
376
+			}
377
+			if (matched) {
378
+				avp = s->avp;
379
+				s->avp = s->avp->next;
380
+				if (val) get_avp_val(avp, val);
381
+				return avp;
382
+			}
383
+		}
340 384
 
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);
385
+		if (IS_USER_AVP(s->flags)) {
386
+			s->flags &= ~AVP_USER;
387
+			s->avp = *crt_domain_avps;
388
+		} else if (IS_DOMAIN_AVP(s->flags)) {
389
+			s->flags &= ~AVP_DOMAIN;
390
+			s->avp = *crt_global_avps;
391
+		} else {
392
+			s->flags &= ~AVP_GLOBAL;
393
+			return 0;
394
+		}
347 395
 	}
348 396
 
349
-	if (next && val) {
350
-		get_avp_val(next, val);
351
-	}
352
-	
353
-	return next;
397
+	return 0;
354 398
 }
355 399
 
356 400
 
... ...
@@ -358,17 +402,16 @@ struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
358 402
 
359 403
 /********* free functions ********/
360 404
 
361
-void destroy_avp( struct usr_avp *avp_del)
405
+void destroy_avp( avp_t *avp_del)
362 406
 {
363
-	struct usr_avp *avp;
364
-	struct usr_avp *avp_prev;
407
+	avp_t *avp, *avp_prev;
365 408
 
366
-	for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
409
+	for( avp_prev=0,avp=*crt_user_avps ; avp ; avp_prev=avp,avp=avp->next ) {
367 410
 		if (avp==avp_del) {
368 411
 			if (avp_prev)
369 412
 				avp_prev->next=avp->next;
370 413
 			else
371
-				*crt_avps = avp->next;
414
+				*crt_user_avps = avp->next;
372 415
 			shm_free(avp);
373 416
 			return;
374 417
 		}
... ...
@@ -376,9 +419,9 @@ void destroy_avp( struct usr_avp *avp_del)
376 419
 }
377 420
 
378 421
 
379
-void destroy_avp_list_unsafe( struct usr_avp **list )
422
+void destroy_avp_list_unsafe( avp_t **list )
380 423
 {
381
-	struct usr_avp *avp, *foo;
424
+	avp_t *avp, *foo;
382 425
 
383 426
 	avp = *list;
384 427
 	while( avp ) {
... ...
@@ -390,9 +433,9 @@ void destroy_avp_list_unsafe( struct usr_avp **list )
390 433
 }
391 434
 
392 435
 
393
-inline void destroy_avp_list( struct usr_avp **list )
436
+inline void destroy_avp_list( avp_t **list )
394 437
 {
395
-	struct usr_avp *avp, *foo;
438
+	avp_t *avp, *foo;
396 439
 
397 440
 	DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
398 441
 	avp = *list;
... ...
@@ -405,29 +448,50 @@ inline void destroy_avp_list( struct usr_avp **list )
405 448
 }
406 449
 
407 450
 
408
-void reset_avps( )
451
+void reset_user_avps(void)
409 452
 {
410
-	assert( crt_avps!=0 );
453
+	assert( crt_user_avps!=0 );
411 454
 	
412
-	if ( crt_avps!=&global_avps) {
413
-		crt_avps = &global_avps;
455
+	if ( crt_user_avps!=&user_avps) {
456
+		crt_user_avps = &user_avps;
414 457
 	}
415
-	destroy_avp_list( crt_avps );
458
+	destroy_avp_list( crt_user_avps );
416 459
 }
417 460
 
418 461
 
419
-struct usr_avp** set_avp_list( struct usr_avp **list )
462
+avp_t** set_user_avp_list( avp_t **list )
420 463
 {
421
-	struct usr_avp **foo;
422
-	
423
-	assert( crt_avps!=0 );
464
+	avp_t **foo;
424 465
 
425
-	foo = crt_avps;
426
-	crt_avps = list;
466
+	assert( crt_user_avps!=0 );
467
+
468
+	foo = crt_user_avps;
469
+	crt_user_avps = list;
427 470
 	return foo;
428 471
 }
429 472
 
430 473
 
474
+avp_t** set_domain_avp_list( avp_t **list )
475
+{
476
+	avp_t **foo;
477
+
478
+	assert( crt_domain_avps!=0 );
479
+
480
+	foo = crt_domain_avps;
481
+	crt_domain_avps = list;
482
+	return foo;
483
+}
484
+
485
+avp_t** set_global_avp_list( avp_t **list )
486
+{
487
+	avp_t **foo;
488
+
489
+	assert( crt_global_avps!=0 );
490
+
491
+	foo = crt_global_avps;
492
+	crt_global_avps = list;
493
+	return foo;
494
+}
431 495
 
432 496
 
433 497
 /********* global aliases functions ********/
... ...
@@ -673,5 +737,3 @@ parse_error:
673 737
 error:
674 738
 	return -1;
675 739
 }
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 73
 } int_str;
69 74
 
70 75
 
71
-struct usr_avp {
76
+typedef struct usr_avp {
72 77
 	unsigned short id;
73 78
 	     /* Flags that are kept for the AVP lifetime */
74 79
 	unsigned short flags;
75
-	     /* Type of search in progress */
76
-	unsigned short search_type;
77 80
 	struct usr_avp *next;
78 81
 	void *data;
82
+} avp_t;
83
+
84
+
85
+/*
86
+ * AVP search state
87
+ */
88
+struct search_state {
89
+	unsigned short flags;  /* Type of search and additional flags */
90
+	unsigned short id;
91
+	int_str name;
92
+	avp_t* avp;            /* Current AVP */
93
+	regex_t* search_re;    /* Compiled regular expression */
79 94
 };
80 95
 
81 96
 
82 97
 #define AVP_NAME_STR     (1<<0)
83 98
 #define AVP_VAL_STR      (1<<1)
84 99
 #define AVP_NAME_RE      (1<<2)
100
+#define AVP_USER         (1<<5)
101
+#define AVP_DOMAIN       (1<<6)
102
+#define AVP_GLOBAL       (1<<7)
103
+
104
+#define ALL_AVP_CLASSES (AVP_USER|AVP_DOMAIN|AVP_GLOBAL)
105
+
106
+/* True for user avps */
107
+#define IS_USER_AVP(flags) ((flags) & AVP_USER)
108
+
109
+/* True for domain avps */
110
+#define IS_DOMAIN_AVP(flags) ((flags) & AVP_DOMAIN)
111
+
112
+/* true for global avps */
113
+#define IS_GLOBAL_AVP(flags) ((flags) & AVP_GLOBAL)
85 114
 
86 115
 #define GALIAS_CHAR_MARKER  '$'
87 116
 
88 117
 /* add functions */
89
-int add_avp( unsigned short flags, int_str name, int_str val);
118
+int add_avp(unsigned short flags, int_str name, int_str val);
90 119
 
91 120
 /* 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  );
121
+avp_t *search_first_avp( unsigned short flags, int_str name,
122
+			 int_str *val, struct search_state* state);
123
+avp_t *search_next_avp(struct search_state* state, int_str *val);
95 124
 
96 125
 /* 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 );
126
+void reset_user_avps(void);
127
+
128
+void destroy_avp(avp_t *avp);
129
+void destroy_avp_list(avp_t **list );
130
+void destroy_avp_list_unsafe(avp_t **list );
101 131
 
102 132
 /* 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( );
133
+void get_avp_val(avp_t *avp, int_str *val );
134
+str* get_avp_name(avp_t *avp);
135
+
136
+avp_t** get_user_avp_list(void);   /* Return current list of user avps */
137
+avp_t** get_domain_avp_list(void); /* Return current list of domain avps */
138
+avp_t** get_global_avp_list(void); /* Return current list of global avps */
139
+
140
+avp_t** set_user_avp_list(avp_t **list);   /* Set current list of user avps to list */
141
+avp_t** set_domain_avp_list(avp_t **list); /* Set current list of domain avps to list */
142
+avp_t** set_global_avp_list(avp_t **list); /* Set current list of global avps to list */
143
+
107 144
 
108 145
 /* global alias functions (manipulation and parsing)*/
109 146
 int add_avp_galias_str(char *alias_definition);