diameter_avp.c

Go to the documentation of this file.
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 /* Start of disc implementation */
00068 
00077 inline void set_avp_fields( AAA_AVPCode code, AAA_AVP *avp)
00078 {
00079     switch (code) {
00080         case   1: /*AVP_User_Name*/
00081         case  25: /*AVP_Class*/
00082         case 263: /*AVP_Session_Id*/
00083         case 283: /*AVP_Destination_Realm*/
00084         case 293: /*AVP Destination Host*/
00085         case 264: /*AVP_Origin_Host*/
00086         case 296: /*AVP Origin_Realm*/
00087             avp->flags = 0x40|(0x20&avp->flags);
00088             avp->type = AAA_AVP_STRING_TYPE;
00089             break;
00090         case  27: /*AVP_Session_Timeout*/
00091         case 258: /*AVP_Auth_Aplication_Id*/
00092         case 262: /*AVP_Redirect_Max_Cache_Time*/
00093         case 265: /*AVP_Supported_Vendor_Id*/
00094         case 266: /*AVP_Vendor_Id*/
00095         case 268: /*AVP_Result_Code*/
00096         case 270: /*AVP_Session_Binding*/
00097         case 276: /*AVP_Auth_Grace_Period*/
00098         case 278: /*AVP_Origin_State_Id*/
00099         case 291: /*AVP_Authorization_Lifetime*/
00100             avp->flags = 0x40|(0x20&avp->flags);
00101             avp->type = AAA_AVP_INTEGER32_TYPE;
00102             break;
00103         case 33: /*AVP_Proxy_State*/
00104             avp->flags = 0x40;
00105             avp->type = AAA_AVP_STRING_TYPE;
00106             break;
00107         case 257: /*AVP_Host_IP_Address*/
00108             avp->flags = 0x40|(0x20&avp->flags);
00109             avp->type = AAA_AVP_ADDRESS_TYPE;
00110             break;
00111         case 269: /*AVP_Product_Name*/
00112             avp->flags = 0x00;
00113             avp->type = AAA_AVP_STRING_TYPE;
00114             break;
00115         case 281: /*AVP_Error_Message*/
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     /* first check the params */
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     /* allocated a new AVP struct */
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     /* set some fields */
00162     //avp->free_it = free_it;
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         /* make a duplicate for data */
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         /* insert at the begining */
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         /* look after avp from position */
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         /* insert after position */
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     /* update the short-cuts */
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     /* param checking */
00275     if (!msg) {
00276         LOG(L_ERR,"ERROR:FindMatchingAVP: param msg passed null !!\n");
00277         goto error;
00278     }
00279 
00280     /* where should I start searching from ? */
00281     if (startAvp) {
00282         /* double-check the startAVP avp */
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         /* if no startAVP -> start from one of the ends */
00292         avp_t=(searchType==AAA_FORWARD_SEARCH)?(msg->avpList.head):
00293             (msg->avpList.tail);
00294     }
00295 
00296     /* start searching */
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     /* param check */
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     /* search the "avp" avp */
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     /* remove the avp from list */
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     /* update short-cuts */
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     /* some checks */
00371     if (!avp || !(*avp)) {
00372         LOG(L_ERR,"ERROR:AAAFreeAVP: param avp cannot be null!!\n");
00373         return AAA_ERR_PARAMETER;
00374     }
00375 
00376     /* free all the mem */
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         //case AAA_AVP_INTEGER64_TYPE:
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     /* clone the avp structure */
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         /* clone the avp data */
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         /* link the clone's data to the original's data */
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 /* End of disc implementation */
00558 
00559 /* Simple extension for grouped avp based on the above implementation  */
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     /* count and add the avps */
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     /* allocate some memory */
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     /* fill in the buffer */
00605     p = (unsigned char*) buf.s;
00606     for(avp=avps.head;avp;avp=avp->next) {
00607         /* AVP HEADER */
00608         /* avp code */
00609         set_4bytes(p,avp->code);
00610         p +=4;
00611         /* flags */
00612         (*p++) = (unsigned char)avp->flags;
00613         /* avp length */
00614         set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
00615         p += 3;
00616         /* vendor id */
00617         if ((avp->flags&0x80)!=0) {
00618             set_4bytes(p,avp->vendorId);
00619             p +=4;
00620         }
00621         /* data */
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     /* start decoding the AVPS */
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         /* avp code */
00663         avp_code = get_4bytes( ptr );
00664         ptr += AVP_CODE_SIZE;
00665         /* avp flags */
00666         avp_flags = (unsigned char)*ptr;
00667         ptr += AVP_FLAGS_SIZE;
00668         /* avp length */
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         /* avp vendor-ID */
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         /* data length */
00684         avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
00685         /*check the data length */
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         /* create the AVP */
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         /* link the avp into aaa message to the end */
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     /* param checking */
00741 
00742     /* where should I start searching from ? */
00743     if (startAvp) {
00744         /* double-check the startAVP avp */
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         /* if no startAVP -> start from one of the ends */
00754         avp_t=(searchType==AAA_FORWARD_SEARCH)?(avpList.head):
00755             (avpList.tail);
00756     }
00757 
00758     /* start searching */
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 }

Generated on Sun Oct 12 04:10:21 2008 for Open IMS Core CSCFs by  doxygen 1.5.2