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
00029
00030
00031
00032
00033
00034
00035
00036 #include <assert.h>
00037 #include <ctype.h>
00038 #include <string.h>
00039 #include <stdlib.h>
00040
00041 #include "sr_module.h"
00042 #include "dprint.h"
00043 #include "str.h"
00044 #include "ut.h"
00045 #include "mem/shm_mem.h"
00046 #include "mem/mem.h"
00047 #include "usr_avp.h"
00048
00049
00050
00051 struct str_int_data {
00052 str name;
00053 int val;
00054 };
00055
00056 struct str_str_data {
00057 str name;
00058 str val;
00059 };
00060
00061
00062 struct avp_spec {
00063 int type;
00064 int_str name;
00065 };
00066
00067 struct avp_galias {
00068 str alias;
00069 struct avp_spec avp;
00070 struct avp_galias *next;
00071 };
00072
00073
00074 static struct avp_galias *galiases = 0;
00075
00076 static struct usr_avp *global_avps = 0;
00077
00078 static struct usr_avp **crt_avps = &global_avps;
00079
00080
00081
00082 inline static unsigned short compute_ID( str *name )
00083 {
00084 char *p;
00085 unsigned short id;
00086
00087 id=0;
00088 for( p=name->s+name->len-1 ; p>=name->s ; p-- )
00089 id ^= *p;
00090 return id;
00091 }
00092
00093
00094 int add_avp(unsigned short flags, int_str name, int_str val)
00095 {
00096 struct usr_avp *avp;
00097 str *s;
00098 struct str_int_data *sid;
00099 struct str_str_data *ssd;
00100 int len;
00101
00102 assert( crt_avps!=0 );
00103
00104 if ( name.n==0 ) {
00105 LM_ERR("0 ID or NULL NAME AVP!");
00106 goto error;
00107 }
00108
00109
00110 len = sizeof(struct usr_avp);
00111 if (flags&AVP_NAME_STR) {
00112 if ( name.s.s==0 || name.s.len==0) {
00113 LM_ERR("empty avp name!");
00114 goto error;
00115 }
00116 if (flags&AVP_VAL_STR)
00117 len += sizeof(struct str_str_data)-sizeof(void*) + name.s.len
00118 + (val.s.len+1);
00119 else
00120 len += sizeof(struct str_int_data)-sizeof(void*) + name.s.len;
00121 } else if (flags&AVP_VAL_STR)
00122 len += sizeof(str)-sizeof(void*) + (val.s.len+1);
00123
00124 avp = (struct usr_avp*)shm_malloc( len );
00125 if (avp==0) {
00126 LM_ERR("no more shm mem\n");
00127 goto error;
00128 }
00129
00130 avp->flags = flags;
00131 avp->id = (flags&AVP_NAME_STR)? compute_ID(&name.s) : name.n ;
00132
00133 avp->next = *crt_avps;
00134 *crt_avps = avp;
00135
00136 switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
00137 {
00138 case 0:
00139
00140 avp->data = (void*)(long)val.n;
00141 break;
00142 case AVP_NAME_STR:
00143
00144 sid = (struct str_int_data*)(void*)&(avp->data);
00145 sid->val = val.n;
00146 sid->name.len =name.s.len;
00147 sid->name.s = (char*)sid + sizeof(struct str_int_data);
00148 memcpy( sid->name.s , name.s.s, name.s.len);
00149 break;
00150 case AVP_VAL_STR:
00151
00152 s = (str*)(void*)&(avp->data);
00153 s->len = val.s.len;
00154 s->s = (char*)s + sizeof(str);
00155 memcpy( s->s, val.s.s , s->len);
00156 s->s[s->len] = 0;
00157 break;
00158 case AVP_NAME_STR|AVP_VAL_STR:
00159
00160 ssd = (struct str_str_data*)(void*)&(avp->data);
00161 ssd->name.len = name.s.len;
00162 ssd->name.s = (char*)ssd + sizeof(struct str_str_data);
00163 memcpy( ssd->name.s , name.s.s, name.s.len);
00164 ssd->val.len = val.s.len;
00165 ssd->val.s = ssd->name.s + ssd->name.len;
00166 memcpy( ssd->val.s , val.s.s, val.s.len);
00167 ssd->val.s[ssd->val.len] = 0;
00168 break;
00169 }
00170
00171 return 0;
00172 error:
00173 return -1;
00174 }
00175
00176
00177
00178
00179 inline str* get_avp_name(struct usr_avp *avp)
00180 {
00181 void *data;
00182 switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
00183 {
00184 case 0:
00185
00186 case AVP_VAL_STR:
00187
00188 return 0;
00189 case AVP_NAME_STR:
00190
00191 data = (void*)&avp->data;
00192 return &((struct str_int_data*)data)->name;
00193 case AVP_NAME_STR|AVP_VAL_STR:
00194
00195 data = (void*)&avp->data;
00196 return &((struct str_str_data*)data)->name;
00197 }
00198
00199 LM_ERR("unknown avp type (name&val) %d\n",
00200 avp->flags&(AVP_NAME_STR|AVP_VAL_STR));
00201 return 0;
00202 }
00203
00204
00205 inline void get_avp_val(struct usr_avp *avp, int_str *val)
00206 {
00207 void *data;
00208
00209 if (avp==0 || val==0)
00210 return;
00211
00212 switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) ) {
00213 case 0:
00214
00215 val->n = (long)(avp->data);
00216 break;
00217 case AVP_NAME_STR:
00218
00219 data = (void*)&avp->data;
00220 val->n = ((struct str_int_data*)data)->val;
00221 break;
00222 case AVP_VAL_STR:
00223
00224 data = (void*)&avp->data;
00225 val->s = *((str*)data);
00226 break;
00227 case AVP_NAME_STR|AVP_VAL_STR:
00228
00229 data = (void*)&avp->data;
00230 val->s = ((struct str_str_data*)data)->val;
00231 break;
00232 }
00233 }
00234
00235
00236 struct usr_avp** get_avp_list(void)
00237 {
00238 assert( crt_avps!=0 );
00239 return crt_avps;
00240 }
00241
00242
00243
00244
00245
00246
00247 inline static struct usr_avp *internal_search_ID_avp( struct usr_avp *avp,
00248 unsigned short id, unsigned short flags)
00249 {
00250 for( ; avp ; avp=avp->next ) {
00251 if ( id==avp->id && (avp->flags&AVP_NAME_STR)==0
00252 && (flags==0 || (flags&avp->flags))) {
00253 return avp;
00254 }
00255 }
00256 return 0;
00257 }
00258
00259
00260
00261 inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
00262 unsigned short id, str *name, unsigned short flags)
00263 {
00264 str * avp_name;
00265
00266 for( ; avp ; avp=avp->next )
00267 if ( id==avp->id && avp->flags&AVP_NAME_STR
00268 && (flags==0 || (flags&avp->flags))
00269 && (avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
00270 && !strncasecmp( avp_name->s, name->s, name->len) ) {
00271 return avp;
00272 }
00273 return 0;
00274 }
00275
00276
00277
00278
00279
00280
00281 struct usr_avp *search_first_avp( unsigned short flags,
00282 int_str name, int_str *val, struct usr_avp *start)
00283 {
00284 struct usr_avp *head;
00285 struct usr_avp *avp;
00286
00287 if(start==0)
00288 {
00289 assert( crt_avps!=0 );
00290
00291 if (*crt_avps==0)
00292 return 0;
00293 head = *crt_avps;
00294 } else {
00295 if(start->next==0)
00296 return 0;
00297 head = start->next;
00298 }
00299
00300 if ( name.n==0) {
00301 LM_ERR("0 ID or NULL NAME AVP!\n");
00302 return 0;
00303 }
00304
00305
00306 if (flags&AVP_NAME_STR) {
00307 if ( name.s.s==0 || name.s.len==0) {
00308 LM_ERR("empty avp name!\n");
00309 return 0;
00310 }
00311 avp = internal_search_name_avp(head,compute_ID(&name.s),&name.s,
00312 flags&AVP_SCRIPT_MASK);
00313 } else {
00314 avp = internal_search_ID_avp(head, name.n,
00315 flags&AVP_SCRIPT_MASK);
00316 }
00317
00318
00319 if (avp && val)
00320 get_avp_val(avp, val);
00321
00322 return avp;
00323 }
00324
00325
00326
00327 struct usr_avp *search_next_avp( struct usr_avp *avp, int_str *val )
00328 {
00329 if (avp==0 || avp->next==0)
00330 return 0;
00331
00332 if (avp->flags&AVP_NAME_STR)
00333 avp = internal_search_name_avp( avp->next, avp->id, get_avp_name(avp),
00334 avp->flags&AVP_SCRIPT_MASK );
00335 else
00336 avp = internal_search_ID_avp( avp->next, avp->id,
00337 avp->flags&AVP_SCRIPT_MASK );
00338
00339 if (avp && val)
00340 get_avp_val(avp, val);
00341
00342 return avp;
00343 }
00344
00345
00346
00347
00348
00349 void destroy_avp( struct usr_avp *avp_del)
00350 {
00351 struct usr_avp *avp;
00352 struct usr_avp *avp_prev;
00353
00354 for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
00355 if (avp==avp_del) {
00356 if (avp_prev)
00357 avp_prev->next=avp->next;
00358 else
00359 *crt_avps = avp->next;
00360 shm_free(avp);
00361 return;
00362 }
00363 }
00364 }
00365
00366
00367 int destroy_avps( unsigned short flags, int_str name, int all)
00368 {
00369 struct usr_avp *avp;
00370 int n;
00371
00372 n = 0;
00373 while ( (avp=search_first_avp( flags, name, 0, 0))!=0 ) {
00374 destroy_avp( avp );
00375 n++;
00376 if ( !all )
00377 break;
00378 }
00379 return n;
00380 }
00381
00382
00383 void destroy_avp_list_unsafe( struct usr_avp **list )
00384 {
00385 struct usr_avp *avp, *foo;
00386
00387 avp = *list;
00388 while( avp ) {
00389 foo = avp;
00390 avp = avp->next;
00391 shm_free_unsafe( foo );
00392 }
00393 *list = 0;
00394 }
00395
00396
00397 inline void destroy_avp_list( struct usr_avp **list )
00398 {
00399 struct usr_avp *avp, *foo;
00400
00401 LM_DBG("destroying list %p\n", *list);
00402 avp = *list;
00403 while( avp ) {
00404 foo = avp;
00405 avp = avp->next;
00406 shm_free( foo );
00407 }
00408 *list = 0;
00409 }
00410
00411
00412 void reset_avps(void)
00413 {
00414 assert( crt_avps!=0 );
00415
00416 if ( crt_avps!=&global_avps) {
00417 crt_avps = &global_avps;
00418 }
00419 destroy_avp_list( crt_avps );
00420 }
00421
00422
00423 struct usr_avp** set_avp_list( struct usr_avp **list )
00424 {
00425 struct usr_avp **foo;
00426
00427 assert( crt_avps!=0 );
00428
00429 foo = crt_avps;
00430 crt_avps = list;
00431 return foo;
00432 }
00433
00434
00435
00436
00437
00438
00439 static inline int check_avp_galias(str *alias, int type, int_str avp_name)
00440 {
00441 struct avp_galias *ga;
00442
00443 type &= AVP_NAME_STR;
00444
00445 for( ga=galiases ; ga ; ga=ga->next ) {
00446
00447 if ( alias->len==ga->alias.len &&
00448 (strncasecmp( alias->s, ga->alias.s, alias->len)==0) )
00449 return -1;
00450
00451 if (type==ga->avp.type) {
00452 if (type&AVP_NAME_STR){
00453 if (avp_name.s.len==ga->avp.name.s.len &&
00454 (strncasecmp(avp_name.s.s, ga->avp.name.s.s,
00455 avp_name.s.len)==0) )
00456 return -1;
00457 } else {
00458 if (avp_name.n==ga->avp.name.n)
00459 return -1;
00460 }
00461 }
00462 }
00463 return 0;
00464 }
00465
00466
00467 int add_avp_galias(str *alias, int type, int_str avp_name)
00468 {
00469 struct avp_galias *ga;
00470
00471 if ((type&AVP_NAME_STR && (!avp_name.s.s ||
00472 !avp_name.s.len)) ||!alias || !alias->s ||
00473 !alias->len ){
00474 LM_ERR("null params received\n");
00475 goto error;
00476 }
00477
00478 if (check_avp_galias(alias,type,avp_name)!=0) {
00479 LM_ERR("duplicate alias/avp entry\n");
00480 goto error;
00481 }
00482
00483 ga = (struct avp_galias*)pkg_malloc( sizeof(struct avp_galias) );
00484 if (ga==0) {
00485 LM_ERR("no more pkg memory\n");
00486 goto error;
00487 }
00488
00489 ga->alias.s = (char*)pkg_malloc( alias->len+1 );
00490 if (ga->alias.s==0) {
00491 LM_ERR("no more pkg memory\n");
00492 goto error1;
00493 }
00494 memcpy( ga->alias.s, alias->s, alias->len);
00495 ga->alias.len = alias->len;
00496
00497 ga->avp.type = type&AVP_NAME_STR;
00498
00499 if (type&AVP_NAME_STR) {
00500 ga->avp.name.s.s = (char*)pkg_malloc(avp_name.s.len+1);
00501 if (ga->avp.name.s.s==0) {
00502 LM_ERR("no more pkg memory\n");
00503 goto error2;
00504 }
00505 ga->avp.name.s.len = avp_name.s.len;
00506 memcpy(ga->avp.name.s.s, avp_name.s.s, avp_name.s.len);
00507 ga->avp.name.s.s[avp_name.s.len] = 0;
00508 LM_DBG("registering <%s> for avp name <%s>\n",
00509 ga->alias.s, ga->avp.name.s.s);
00510 } else {
00511 ga->avp.name.n = avp_name.n;
00512 LM_DBG("registering <%s> for avp id <%d>\n",
00513 ga->alias.s, ga->avp.name.n);
00514 }
00515
00516 ga->next = galiases;
00517 galiases = ga;
00518
00519 return 0;
00520 error2:
00521 pkg_free(ga->alias.s);
00522 error1:
00523 pkg_free(ga);
00524 error:
00525 return -1;
00526 }
00527
00528
00529 int lookup_avp_galias(str *alias, int *type, int_str *avp_name)
00530 {
00531 struct avp_galias *ga;
00532
00533 for( ga=galiases ; ga ; ga=ga->next )
00534 if (alias->len==ga->alias.len &&
00535 (strncasecmp( alias->s, ga->alias.s, alias->len)==0) ) {
00536 *type = ga->avp.type;
00537 *avp_name = ga->avp.name;
00538 return 0;
00539 }
00540
00541 return -1;
00542 }
00543
00544
00545
00546
00547 int parse_avp_name( str *name, int *type, int_str *avp_name)
00548 {
00549 unsigned int id;
00550 unsigned int flags;
00551 char *p;
00552 char c;
00553 str s;
00554
00555 if (name==0 || name->s==0 || name->len==0)
00556 goto error;
00557
00558 p = (char*)memchr((void*)name->s, AVP_NAME_DELIM, name->len);
00559 c = name->s[0];
00560 if((c!='i' && c!='I' && c!='s' && c!='S') || p==NULL)
00561 {
00562 LM_ERR("- use type (s: or i:) in front of avp name\n");
00563 goto error;
00564 }
00565
00566 flags = 0;
00567 if(p>name->s+1)
00568 {
00569 s.s = name->s+1;
00570 s.len = p - s.s;
00571 if(str2int(&s, &flags)!=0)
00572 {
00573 LM_ERR("bad avp flags\n");
00574 goto error;
00575 }
00576 }
00577 name->len -= p-name->s+1;
00578 name->s = p+1;
00579 switch (c) {
00580 case 's': case 'S':
00581 *type = AVP_NAME_STR;
00582 avp_name->s = *name;
00583 break;
00584 case 'i': case 'I':
00585 *type = 0;
00586 if (str2int( name, &id)!=0) {
00587 LM_ERR("invalid ID <%.*s> not a number\n", name->len, name->s);
00588 goto error;
00589 }
00590 avp_name->n = (int)id;
00591 break;
00592 default:
00593 LM_ERR("unsupported type [%c]\n", c);
00594 goto error;
00595 }
00596
00597 *type |= avp_script_flags(flags);
00598 return 0;
00599 error:
00600 return -1;
00601 }
00602
00603
00604 int parse_avp_spec( str *name, int *type, int_str *avp_name)
00605 {
00606 char *p;
00607
00608 if (name==0 || name->s==0 || name->len==0)
00609 return -1;
00610
00611 p = (char*)memchr((void*)name->s, AVP_NAME_DELIM, name->len);
00612 if (p==NULL) {
00613
00614 return lookup_avp_galias( name, type, avp_name);
00615 } else {
00616 return parse_avp_name( name, type, avp_name);
00617 }
00618 }
00619
00620
00621 int add_avp_galias_str(char *alias_definition)
00622 {
00623 int_str avp_name;
00624 char *s;
00625 str name;
00626 str alias;
00627 int type;
00628
00629 s = alias_definition;
00630 while(*s && isspace((int)*s))
00631 s++;
00632
00633 while (*s) {
00634
00635 alias.s = s;
00636 while(*s && *s!=';' && !isspace((int)*s) && *s!='=')
00637 s++;
00638 if (alias.s==s || *s==0 || *s==';')
00639 goto parse_error;
00640 alias.len = s-alias.s;
00641 while(*s && isspace((int)*s))
00642 s++;
00643
00644 if (*s!='=')
00645 goto parse_error;
00646 s++;
00647 while(*s && isspace((int)*s))
00648 s++;
00649
00650 name.s = s;
00651 while(*s && *s!=';' && !isspace((int)*s))
00652 s++;
00653 if (name.s==s)
00654 goto parse_error;
00655 name.len = s-name.s;
00656 while(*s && isspace((int)*s))
00657 s++;
00658
00659 if (*s!=0 && *s!=';')
00660 goto parse_error;
00661 if (*s==';') {
00662 for( s++ ; *s && isspace((int)*s) ; s++ );
00663 if (*s==0)
00664 goto parse_error;
00665 }
00666
00667 if (parse_avp_name( &name, &type, &avp_name)!=0) {
00668 LM_ERR("<%.*s> not a valid AVP name\n", name.len, name.s);
00669 goto error;
00670 }
00671
00672 if (add_avp_galias( &alias, type, avp_name)!=0) {
00673 LM_ERR("add global alias failed\n");
00674 goto error;
00675 }
00676 }
00677
00678 return 0;
00679 parse_error:
00680 LM_ERR("parse error in <%s> around pos %ld\n",
00681 alias_definition, (long)(s-alias_definition));
00682 error:
00683 return -1;
00684 }