00001
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #include <netinet/in.h>
00062
00063 #include "diameter.h"
00064 #include "utils.h"
00065
00066
00067
00068
00077 inline void set_avp_fields( AAA_AVPCode code, AAA_AVP *avp)
00078 {
00079 switch (code) {
00080 case 1:
00081 case 25:
00082 case 263:
00083 case 283:
00084 case 293:
00085 case 264:
00086 case 296:
00087 avp->flags = 0x40|(0x20&avp->flags);
00088 avp->type = AAA_AVP_STRING_TYPE;
00089 break;
00090 case 27:
00091 case 258:
00092 case 262:
00093 case 265:
00094 case 266:
00095 case 268:
00096 case 270:
00097 case 276:
00098 case 278:
00099 case 291:
00100 avp->flags = 0x40|(0x20&avp->flags);
00101 avp->type = AAA_AVP_INTEGER32_TYPE;
00102 break;
00103 case 33:
00104 avp->flags = 0x40;
00105 avp->type = AAA_AVP_STRING_TYPE;
00106 break;
00107 case 257:
00108 avp->flags = 0x40|(0x20&avp->flags);
00109 avp->type = AAA_AVP_ADDRESS_TYPE;
00110 break;
00111 case 269:
00112 avp->flags = 0x00;
00113 avp->type = AAA_AVP_STRING_TYPE;
00114 break;
00115 case 281:
00116 avp->flags = (0x20&avp->flags);
00117 avp->type = AAA_AVP_STRING_TYPE;
00118 break;
00119 default:
00120 avp->type = AAA_AVP_DATA_TYPE;
00121 };
00122 }
00123
00124
00125
00137 AAA_AVP* AAACreateAVP(
00138 AAA_AVPCode code,
00139 AAA_AVPFlag flags,
00140 AAAVendorId vendorId,
00141 char *data,
00142 size_t length,
00143 AVPDataStatus data_status)
00144 {
00145 AAA_AVP *avp;
00146
00147
00148 if( data==0 || length==0) {
00149 LOG(L_ERR,"ERROR:AAACreateAVP: NULL value received for"
00150 " param data/length !!\n");
00151 return 0;
00152 }
00153
00154
00155 avp = 0;
00156 avp = (AAA_AVP*)shm_malloc(sizeof(AAA_AVP));
00157 if (!avp)
00158 goto error;
00159 memset( avp, 0, sizeof(AAA_AVP) );
00160
00161
00162
00163 avp->code=code;
00164 avp->flags=flags;
00165 avp->vendorId=vendorId;
00166 set_avp_fields( code, avp);
00167
00168 if ( data_status==AVP_DUPLICATE_DATA ) {
00169
00170 avp->data.len = length;
00171 avp->data.s = (void*)shm_malloc(length);
00172 if(!avp->data.s)
00173 goto error;
00174 memcpy( avp->data.s, data, length);
00175 avp->free_it = 1;
00176 } else {
00177 avp->data.s = data;
00178 avp->data.len = length;
00179 avp->free_it = (data_status==AVP_FREE_DATA)?1:0;
00180 }
00181
00182 return avp;
00183 error:
00184 LOG(L_ERR,"ERROR:AAACreateAVP: no more free memory!\n");
00185 return 0;
00186 }
00187
00188
00189
00198 AAAReturnCode AAAAddAVPToMessage(
00199 AAAMessage *msg,
00200 AAA_AVP *avp,
00201 AAA_AVP *position)
00202 {
00203 AAA_AVP *avp_t;
00204
00205 if ( !msg || !avp ) {
00206 LOG(L_ERR,"ERROR:AAAAddAVPToList: param msg or avp passed null"
00207 " or *avpList=NULL and position!=NULL !!\n");
00208 return AAA_ERR_PARAMETER;
00209 }
00210
00211 if (!position) {
00212
00213 avp->next = msg->avpList.head;
00214 avp->prev = 0;
00215 msg->avpList.head = avp;
00216 if (avp->next)
00217 avp->next->prev = avp;
00218 else
00219 msg->avpList.tail = avp;
00220 } else {
00221
00222 for(avp_t=msg->avpList.head;avp_t&&avp_t!=position;avp_t=avp_t->next);
00223 if (!avp_t) {
00224 LOG(L_ERR,"ERROR: AAACreateAVP: the \"position\" avp is not in"
00225 "\"msg\" message!!\n");
00226 return AAA_ERR_PARAMETER;
00227 }
00228
00229 avp->next = position->next;
00230 position->next = avp;
00231 if (avp->next)
00232 avp->next->prev = avp;
00233 else
00234 msg->avpList.tail = avp;
00235 avp->prev = position;
00236 }
00237
00238
00239 switch (avp->code) {
00240 case AVP_Session_Id: msg->sessionId = avp;break;
00241 case AVP_Origin_Host: msg->orig_host = avp;break;
00242 case AVP_Origin_Realm: msg->orig_realm = avp;break;
00243 case AVP_Destination_Host: msg->dest_host = avp;break;
00244 case AVP_Destination_Realm: msg->dest_realm = avp;break;
00245 case AVP_Result_Code: msg->res_code = avp;break;
00246 case AVP_Auth_Session_State: msg->auth_ses_state = avp;break;
00247 }
00248
00249 return AAA_ERR_SUCCESS;
00250 }
00251
00252
00253
00265 AAA_AVP *AAAFindMatchingAVP(
00266 AAAMessage *msg,
00267 AAA_AVP *startAvp,
00268 AAA_AVPCode avpCode,
00269 AAAVendorId vendorId,
00270 AAASearchType searchType)
00271 {
00272 AAA_AVP *avp_t;
00273
00274
00275 if (!msg) {
00276 LOG(L_ERR,"ERROR:FindMatchingAVP: param msg passed null !!\n");
00277 goto error;
00278 }
00279
00280
00281 if (startAvp) {
00282
00283 for(avp_t=msg->avpList.head;avp_t&&avp_t!=startAvp;avp_t=avp_t->next);
00284 if (!avp_t) {
00285 LOG(L_ERR,"ERROR: AAAFindMatchingAVP: the \"position\" avp is not "
00286 "in \"avpList\" list!!\n");
00287 goto error;
00288 }
00289 avp_t=startAvp;
00290 } else {
00291
00292 avp_t=(searchType==AAA_FORWARD_SEARCH)?(msg->avpList.head):
00293 (msg->avpList.tail);
00294 }
00295
00296
00297 while(avp_t) {
00298 if (avp_t->code==avpCode && avp_t->vendorId==vendorId)
00299 return avp_t;
00300 avp_t = (searchType==AAA_FORWARD_SEARCH)?(avp_t->next):(avp_t->prev);
00301 }
00302
00303 error:
00304 return 0;
00305 }
00306
00307
00308
00316 AAAReturnCode AAARemoveAVPFromMessage(
00317 AAAMessage *msg,
00318 AAA_AVP *avp)
00319 {
00320 AAA_AVP *avp_t;
00321
00322
00323 if ( !msg || !avp ) {
00324 LOG(L_ERR,"ERROR:AAAAddAVPToList: param AVP_LIST \"avpList\" or AVP "
00325 "\"avp\" passed null !!\n");
00326 return AAA_ERR_PARAMETER;
00327 }
00328
00329
00330 for(avp_t=msg->avpList.head;avp_t&&avp_t!=avp;avp_t=avp_t->next);
00331 if (!avp_t) {
00332 LOG(L_ERR,"ERROR: AAACreateAVP: the \"avp\" avp is not in "
00333 "\"avpList\" avp list!!\n");
00334 return AAA_ERR_PARAMETER;
00335 }
00336
00337
00338 if (msg->avpList.head==avp)
00339 msg->avpList.head = avp->next;
00340 else
00341 avp->prev->next = avp->next;
00342 if (avp->next)
00343 avp->next->prev = avp->prev;
00344 else
00345 msg->avpList.tail = avp->prev;
00346 avp->next = avp->prev = 0;
00347
00348
00349 switch (avp->code) {
00350 case AVP_Session_Id: msg->sessionId = 0;break;
00351 case AVP_Origin_Host: msg->orig_host = 0;break;
00352 case AVP_Origin_Realm: msg->orig_realm = 0;break;
00353 case AVP_Destination_Host: msg->dest_host = 0;break;
00354 case AVP_Destination_Realm: msg->dest_realm = 0;break;
00355 case AVP_Result_Code: msg->res_code = 0;break;
00356 case AVP_Auth_Session_State: msg->auth_ses_state = 0;break;
00357 }
00358
00359 return AAA_ERR_SUCCESS;
00360 }
00361
00362
00363
00368 AAAReturnCode AAAFreeAVP(AAA_AVP **avp)
00369 {
00370
00371 if (!avp || !(*avp)) {
00372 LOG(L_ERR,"ERROR:AAAFreeAVP: param avp cannot be null!!\n");
00373 return AAA_ERR_PARAMETER;
00374 }
00375
00376
00377 if ( (*avp)->free_it && (*avp)->data.s )
00378 shm_free((*avp)->data.s);
00379
00380 shm_free( *avp );
00381 avp = 0;
00382
00383 return AAA_ERR_SUCCESS;
00384 }
00385
00386
00387
00393 AAA_AVP* AAAGetFirstAVP(AAA_AVP_LIST *avpList){
00394 return avpList->head;
00395 }
00396
00397
00398
00404 AAA_AVP* AAAGetLastAVP(AAA_AVP_LIST *avpList)
00405 {
00406 return avpList->tail;
00407 }
00408
00409
00410
00411
00418 AAA_AVP* AAAGetNextAVP(AAA_AVP *avp)
00419 {
00420 return avp->next;
00421 }
00422
00423
00424
00431 AAA_AVP* AAAGetPrevAVP(AAA_AVP *avp)
00432 {
00433 return avp->prev;
00434 }
00435
00436
00437
00447 char* AAAConvertAVPToString(AAA_AVP *avp, char *dest, unsigned int destLen)
00448 {
00449 int l;
00450 int i;
00451
00452 if (!avp || !dest || !destLen) {
00453 LOG(L_ERR,"ERROR:AAAConvertAVPToString: param AVP, DEST or DESTLEN "
00454 "passed as null!!!\n");
00455 return 0;
00456 }
00457 l = snprintf(dest,destLen,"AVP(%p < %p >%p);code=%u,"
00458 "flags=%x;\nDataType=%u;VendorID=%u;DataLen=%u;\n",
00459 avp->prev,avp,avp->next,avp->code,avp->flags,
00460 avp->type,avp->vendorId,avp->data.len);
00461 switch(avp->type) {
00462 case AAA_AVP_STRING_TYPE:
00463 l+=snprintf(dest+l,destLen-l,"String: <%.*s>",avp->data.len,
00464 avp->data.s);
00465 break;
00466 case AAA_AVP_INTEGER32_TYPE:
00467 l+=snprintf(dest+l,destLen-l,"Int32: <%u>(%x)",
00468 htonl(*((unsigned int*)avp->data.s)),
00469 htonl(*((unsigned int*)avp->data.s)));
00470 break;
00471 case AAA_AVP_ADDRESS_TYPE:
00472 i = 1;
00473 switch (avp->data.len) {
00474 case 4: i=i*0;
00475 case 6: i=i*2;
00476 l+=snprintf(dest+l,destLen-l,"Address IPv4: <%d.%d.%d.%d>",
00477 (unsigned char)avp->data.s[i+0],
00478 (unsigned char)avp->data.s[i+1],
00479 (unsigned char)avp->data.s[i+2],
00480 (unsigned char)avp->data.s[i+3]);
00481 break;
00482 case 16: i=i*0;
00483 case 18: i=i*2;
00484 l+=snprintf(dest+l,destLen-l,
00485 "Address IPv6: <%x.%x.%x.%x.%x.%x.%x.%x>",
00486 ((avp->data.s[i+0]<<8)+avp->data.s[i+1]),
00487 ((avp->data.s[i+2]<<8)+avp->data.s[i+3]),
00488 ((avp->data.s[i+4]<<8)+avp->data.s[i+5]),
00489 ((avp->data.s[i+6]<<8)+avp->data.s[i+7]),
00490 ((avp->data.s[i+8]<<8)+avp->data.s[i+9]),
00491 ((avp->data.s[i+10]<<8)+avp->data.s[i+11]),
00492 ((avp->data.s[i+12]<<8)+avp->data.s[i+13]),
00493 ((avp->data.s[i+14]<<8)+avp->data.s[i+15]));
00494 break;
00495 break;
00496 }
00497 break;
00498
00499 case AAA_AVP_TIME_TYPE:
00500 default:
00501 LOG(L_WARN,"WARNING:AAAConvertAVPToString: don't know how to print"
00502 " this data type [%d] -> tryng hexa\n",avp->type);
00503 case AAA_AVP_DATA_TYPE:
00504 for (i=0;i<avp->data.len&&l<destLen-1;i++)
00505 l+=snprintf(dest+l,destLen-l-1,"%x",
00506 ((unsigned char*)avp->data.s)[i]);
00507 }
00508 return dest;
00509 }
00510
00511
00519 AAA_AVP* AAACloneAVP( AAA_AVP *avp , unsigned char clone_data)
00520 {
00521 AAA_AVP *n_avp;
00522
00523 if (!avp || !(avp->data.s) || !(avp->data.len) )
00524 goto error;
00525
00526
00527 n_avp = (AAA_AVP*)shm_malloc( sizeof(AAA_AVP) );
00528 if (!n_avp) {
00529 LOG(L_ERR,"ERROR:clone_avp: cannot get free memory!!\n");
00530 goto error;
00531 }
00532 memcpy( n_avp, avp, sizeof(AAA_AVP));
00533 n_avp->next = n_avp->prev = 0;
00534
00535 if (clone_data) {
00536
00537 n_avp->data.s = (char*)shm_malloc( avp->data.len );
00538 if (!(n_avp->data.s)) {
00539 LOG(L_ERR,"ERROR:clone_avp: cannot get free memory!!\n");
00540 shm_free( n_avp );
00541 goto error;
00542 }
00543 memcpy( n_avp->data.s, avp->data.s, avp->data.len);
00544 n_avp->free_it = 1;
00545 } else {
00546
00547 n_avp->data.s = avp->data.s;
00548 n_avp->data.len = avp->data.len;
00549 n_avp->free_it = 0;
00550 }
00551
00552 return n_avp;
00553 error:
00554 return 0;
00555 }
00556
00557
00558
00559
00560
00566 void AAAAddAVPtoList(AAA_AVP_LIST *list,AAA_AVP *avp)
00567 {
00568 if (list->tail) {
00569 avp->prev=list->tail;
00570 avp->next=0;
00571 list->tail->next = avp;
00572 list->tail=avp;
00573 } else {
00574 list->head = avp;
00575 list->tail = avp;
00576 avp->next=0;
00577 avp->prev=0;
00578 }
00579 }
00580
00585 str AAAGroupAVPS(AAA_AVP_LIST avps)
00586 {
00587 AAA_AVP *avp;
00588 unsigned char *p;
00589 str buf={0,0};
00590
00591
00592 for(avp=avps.head;avp;avp=avp->next) {
00593 buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
00594 }
00595
00596 if (!buf.len) return buf;
00597
00598 buf.s = (char*)shm_malloc( buf.len );
00599 if (!buf.s) {
00600 LOG(L_ERR,"ERROR:hss3g_group_avps: no more free memory!\n");
00601 return buf;
00602 }
00603 memset(buf.s, 0, buf.len);
00604
00605 p = (unsigned char*) buf.s;
00606 for(avp=avps.head;avp;avp=avp->next) {
00607
00608
00609 set_4bytes(p,avp->code);
00610 p +=4;
00611
00612 (*p++) = (unsigned char)avp->flags;
00613
00614 set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
00615 p += 3;
00616
00617 if ((avp->flags&0x80)!=0) {
00618 set_4bytes(p,avp->vendorId);
00619 p +=4;
00620 }
00621
00622 memcpy( p, avp->data.s, avp->data.len);
00623 p += to_32x_len( avp->data.len );
00624 }
00625 if ((char*)p-buf.s!=buf.len) {
00626 LOG(L_ERR,"BUG:hss3g_group_avps: mismatch between len and buf!\n");
00627 shm_free( buf.s );
00628 buf.s = 0;
00629 buf.len = 0;
00630 return buf;
00631 }
00632 return buf;
00633 }
00634
00640 AAA_AVP_LIST AAAUngroupAVPS(str buf)
00641 {
00642 char *ptr;
00643 AAA_AVP *avp;
00644 unsigned int avp_code;
00645 unsigned char avp_flags;
00646 unsigned int avp_len;
00647 unsigned int avp_vendorID;
00648 unsigned int avp_data_len;
00649 AAA_AVP_LIST lh;
00650
00651 lh.head=0;
00652 lh.tail=0;
00653 ptr = buf.s;
00654
00655
00656 while (ptr < buf.s+buf.len) {
00657 if (ptr+AVP_HDR_SIZE(0x80)>buf.s+buf.len){
00658 LOG(L_ERR,"ERROR:hss3g_ungroup_avps: source buffer to short!! "
00659 "Cannot read the whole AVP header!\n");
00660 goto error;
00661 }
00662
00663 avp_code = get_4bytes( ptr );
00664 ptr += AVP_CODE_SIZE;
00665
00666 avp_flags = (unsigned char)*ptr;
00667 ptr += AVP_FLAGS_SIZE;
00668
00669 avp_len = get_3bytes( ptr );
00670 ptr += AVP_LENGTH_SIZE;
00671 if (avp_len<1) {
00672 LOG(L_ERR,"ERROR:hss3g_ungroup_avps: invalid AVP len [%d]\n",
00673 avp_len);
00674 goto error;
00675 }
00676
00677 avp_vendorID = 0;
00678 if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
00679 avp_vendorID = get_4bytes( ptr );
00680 ptr += AVP_VENDOR_ID_SIZE;
00681 }
00682
00683
00684 avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
00685
00686 if ( buf.s+buf.len<ptr+avp_data_len) {
00687 LOG(L_ERR,"ERROR:hss3g_ungroup_avps: source buffer to short!! "
00688 "Cannot read a whole data for AVP!\n");
00689 goto error;
00690 }
00691
00692
00693 avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, ptr,
00694 avp_data_len, AVP_DONT_FREE_DATA);
00695 if (!avp) {
00696 LOG(L_ERR,"ERROR:hss3g_ungroup_avps: can't create avp for member of list\n");
00697 goto error;
00698 }
00699
00700
00701 avp->next = 0;
00702 avp->prev = lh.tail;
00703 if (lh.tail) {
00704 lh.tail->next=avp;
00705 lh.tail=avp;
00706 }
00707 else {
00708 lh.tail=avp;
00709 lh.head=avp;
00710 }
00711
00712 ptr += to_32x_len( avp_data_len );
00713 }
00714 return lh;
00715
00716 error:
00717 LOG(L_CRIT,"AVP:<%.*s>\n",buf.len,buf.s);
00718 return lh;
00719 }
00720
00731 AAA_AVP *AAAFindMatchingAVPList(
00732 AAA_AVP_LIST avpList,
00733 AAA_AVP *startAvp,
00734 AAA_AVPCode avpCode,
00735 AAAVendorId vendorId,
00736 AAASearchType searchType)
00737 {
00738 AAA_AVP *avp_t;
00739
00740
00741
00742
00743 if (startAvp) {
00744
00745 for(avp_t=avpList.head;avp_t&&avp_t!=startAvp;avp_t=avp_t->next);
00746 if (!avp_t) {
00747 LOG(L_ERR,"ERROR: AAAFindMatchingAVP: the \"position\" avp is not "
00748 "in \"avpList\" list!!\n");
00749 goto error;
00750 }
00751 avp_t=startAvp;
00752 } else {
00753
00754 avp_t=(searchType==AAA_FORWARD_SEARCH)?(avpList.head):
00755 (avpList.tail);
00756 }
00757
00758
00759 while(avp_t) {
00760 if (avp_t->code==avpCode && avp_t->vendorId==vendorId)
00761 return avp_t;
00762 avp_t = (searchType==AAA_FORWARD_SEARCH)?(avp_t->next):(avp_t->prev);
00763 }
00764
00765 error:
00766 return 0;
00767 }
00768
00774 void AAAAddAVPToAVPList(AAA_AVP_LIST *list,AAA_AVP *avp)
00775 {
00776 if (list->tail) {
00777 avp->prev=list->tail;
00778 avp->next=0;
00779 list->tail->next = avp;
00780 list->tail=avp;
00781 } else {
00782 list->head = avp;
00783 list->tail = avp;
00784 avp->next=0;
00785 avp->prev=0;
00786 }
00787 }