diam_avp.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2002-2003 FhG Fokus
00005  *
00006  * This file is part of disc, a free diameter server/client.
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * --------
00024  * 2002-10-04 created  by illya (komarov@fokus.gmd.de)
00025  * 2003-03-12 converted to shm_malloc/free (andrei)
00026  *
00027  */
00028 
00036 #ifdef DIAM_ACC
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <netinet/in.h>
00042 
00043 #include "../../mem/shm_mem.h"
00044 #include "../../dprint.h"
00045 #include "diam_message.h"
00046 
00047 
00048 
00049 /*
00050  * each AVP type has some default set/reset flags and a proper data type.
00051  * All this default values (for flags and data-type) are correct/set by this
00052  * function.
00053  */
00054 inline void set_avp_fields( AAA_AVPCode code, AAA_AVP *avp)
00055 {
00056         switch (code) {
00057                 case   1: /*AVP_User_Name*/
00058                 case  25: /*AVP_Class*/
00059                 case 263: /*AVP_Session_Id*/
00060                 case 283: /*AVP_Destination_Realm*/
00061                 case 293: /*AVP Destination Host*/
00062                 case 264: /*AVP_Origin_Host*/
00063                 case 296: /*AVP Origin_Realm*/
00064                 case 400: /* AVP_Resource */    
00065                 case 401: /* AVP_Response */    
00066                 case 402: /* AVP_Chalenge */    
00067                 case 403: /* AVP_Method */
00068                 case 404: /* Service_Type AVP */
00069                 case 405: /* User_Group AVP*/
00070                 case 279:                                       
00071                         avp->flags = 0x40|(0x20&avp->flags);
00072                         avp->type = AAA_AVP_STRING_TYPE;
00073                         break;
00074                 case  27: /*AVP_Session_Timeout*/
00075                 case 258: /*AVP_Auth_Aplication_Id*/
00076                 case 262: /*AVP_Redirect_Max_Cache_Time*/
00077                 case 265: /*AVP_Supported_Vendor_Id*/
00078                 case 266: /*AVP_Vendor_Id*/
00079                 case 268: /*AVP_Result_Code*/
00080                 case 270: /*AVP_Session_Binding*/
00081                 case 276: /*AVP_Auth_Grace_Period*/
00082                 case 278: /*AVP_Origin_State_Id*/
00083                 case 291: /*AVP_Authorization_Lifetime*/
00084                         avp->flags = 0x40|(0x20&avp->flags);
00085                         avp->type = AAA_AVP_INTEGER32_TYPE;
00086                         break;
00087                 case 33: /*AVP_Proxy_State*/
00088                         avp->flags = 0x40;
00089                         avp->type = AAA_AVP_STRING_TYPE;
00090                         break;
00091                 case 257: /*AVP_Host_IP_Address*/
00092                         avp->flags = 0x40|(0x20&avp->flags);
00093                         avp->type = AAA_AVP_ADDRESS_TYPE;
00094                         break;
00095                 case 269: /*AVP_Product_Name*/
00096                         avp->flags = 0x00;
00097                         avp->type = AAA_AVP_STRING_TYPE;
00098                         break;
00099                 case 281: /*AVP_Error_Message*/
00100                         avp->flags = (0x20&avp->flags);
00101                         avp->type = AAA_AVP_STRING_TYPE;
00102                         break;
00103                 default:
00104                         avp->type = AAA_AVP_DATA_TYPE;
00105         };
00106 }
00107 
00108 
00109 
00110 /* This function creates an AVP and returns a pointer to it;
00111  */
00112 AAA_AVP*  AAACreateAVP(
00113         AAA_AVPCode code,
00114         AAA_AVPFlag flags,
00115         AAAVendorId vendorId,
00116         char   *data,
00117         size_t length,
00118         AVPDataStatus data_status)
00119 {
00120         AAA_AVP *avp;
00121 
00122         /* first check the params */
00123         if( data==0 || length==0) {
00124                 LM_ERR("null value received for param data/length !!\n");
00125                 return 0;
00126         }
00127 
00128         /* allocated a new AVP struct */
00129         avp = 0;
00130         avp = (AAA_AVP*)ad_malloc(sizeof(AAA_AVP));
00131         if (!avp)
00132                 goto error;
00133         memset( avp, 0, sizeof(AAA_AVP) );
00134 
00135         /* set some fields */
00136         //avp->free_it = free_it;
00137         avp->packetType = AAA_DIAMETER;
00138         avp->code=code;
00139         avp->flags=flags;
00140         avp->vendorId=vendorId;
00141         set_avp_fields( code, avp);
00142 
00143         if ( data_status==AVP_DUPLICATE_DATA ) {
00144                 /* make a duplicate for data */
00145                 avp->data.len = length;
00146                 avp->data.s = (void*)ad_malloc(length);
00147                 if(!avp->data.s)
00148                         goto error;
00149                 memcpy( avp->data.s, data, length);
00150                 avp->free_it = 1;
00151         } else {
00152                 avp->data.s = data;
00153                 avp->data.len = length;
00154                 avp->free_it = (data_status==AVP_FREE_DATA)?1:0;
00155         }
00156 
00157         return avp;
00158 error:
00159         LM_ERR("no more free memoryfor a new AVP!\n");
00160         return 0;
00161 }
00162 
00163 
00164 
00165 /* Insert the AVP avp into this avpList of a message after position */
00166 AAAReturnCode  AAAAddAVPToMessage(
00167         AAAMessage *msg,
00168         AAA_AVP *avp,
00169         AAA_AVP *position)
00170 {
00171         AAA_AVP *avp_t;
00172 
00173         if ( !msg || !avp ) {
00174                 LM_ERR("param msg or avp passed null or *avpList=NULL "
00175                                 "and position!=NULL !!\n");
00176                 return AAA_ERR_PARAMETER;
00177         }
00178 
00179         if (!position) {
00180                 /* insert at the beginning */
00181                 avp->next = msg->avpList.head;
00182                 avp->prev = 0;
00183                 msg->avpList.head = avp;
00184                 if (avp->next)
00185                         avp->next->prev = avp;
00186                 else
00187                         msg->avpList.tail = avp;
00188         } else {
00189                 /* look after avp from position */
00190                 for(avp_t=msg->avpList.head;avp_t&&avp_t!=position;avp_t=avp_t->next);
00191                 if (!avp_t) {
00192                         LM_ERR("the \"position\" avp is not in \"msg\" message!!\n");
00193                         return AAA_ERR_PARAMETER;
00194                 }
00195                 /* insert after position */
00196                 avp->next = position->next;
00197                 position->next = avp;
00198                 if (avp->next)
00199                         avp->next->prev = avp;
00200                 else
00201                         msg->avpList.tail = avp;
00202                 avp->prev = position;
00203         }
00204 
00205         /* update the short-cuts */
00206         switch (avp->code) {
00207                 case AVP_Session_Id: msg->sessionId = avp;break;
00208                 case AVP_Origin_Host: msg->orig_host = avp;break;
00209                 case AVP_Origin_Realm: msg->orig_realm = avp;break;
00210                 case AVP_Destination_Host: msg->dest_host = avp;break;
00211                 case AVP_Destination_Realm: msg->dest_realm = avp;break;
00212                 case AVP_Result_Code: msg->res_code = avp;break;
00213                 case AVP_Auth_Session_State: msg->auth_ses_state = avp;break;
00214         }
00215 
00216         return AAA_ERR_SUCCESS;
00217 }
00218 
00219 
00220 /* This function finds an AVP with matching code and vendor id */
00221 AAA_AVP  *AAAFindMatchingAVP(
00222         AAAMessage *msg,
00223         AAA_AVP *startAvp,
00224         AAA_AVPCode avpCode,
00225         AAAVendorId vendorId,
00226         AAASearchType searchType)
00227 {
00228         AAA_AVP *avp_t;
00229 
00230         /* param checking */
00231         if (!msg) {
00232                 LM_ERR("param msg passed null !!\n");
00233                 goto error;
00234         }
00235         /* search the startAVP avp */
00236         for(avp_t=msg->avpList.head;avp_t&&avp_t!=startAvp;avp_t=avp_t->next);
00237         if (!avp_t && startAvp) {
00238                 LM_ERR("the \"position\" avp is not in \"avpList\" list!!\n");
00239                 goto error;
00240         }
00241 
00242         /* where should I start searching from ? */
00243         if (!startAvp)
00244                 avp_t=(searchType==AAA_FORWARD_SEARCH)?(msg->avpList.head):
00245                         (msg->avpList.tail);
00246         else
00247                 avp_t=startAvp;
00248 
00249         /* start searching */
00250         while(avp_t) {
00251                 if (avp_t->code==avpCode && avp_t->vendorId==vendorId)
00252                         return avp_t;
00253                 avp_t = (searchType==AAA_FORWARD_SEARCH)?(avp_t->next):(avp_t->prev);
00254         }
00255 
00256 error:
00257         return 0;
00258 }
00259 
00260 
00261 
00262 
00263 /* This function removes an AVP from a list of a message */
00264 AAAReturnCode  AAARemoveAVPFromMessage(
00265         AAAMessage *msg,
00266         AAA_AVP *avp)
00267 {
00268         AAA_AVP *avp_t;
00269 
00270         /* param check */
00271         if ( !msg || !avp ) {
00272                 LM_ERR("param AVP_LIST \"avpList\" or AVP \"avp\" passed null !!\n");
00273                 return AAA_ERR_PARAMETER;
00274         }
00275 
00276         /* search the "avp" avp */
00277         for(avp_t=msg->avpList.head;avp_t&&avp_t!=avp;avp_t=avp_t->next);
00278         if (!avp_t) {
00279                 LM_ERR("the \"avp\" avp is not in \"avpList\" avp list!!\n");
00280                 return AAA_ERR_PARAMETER;
00281         }
00282 
00283         /* remove the avp from list */
00284         if (msg->avpList.head==avp)
00285                 msg->avpList.head = avp->next;
00286         else
00287                 avp->prev->next = avp->next;
00288         if (avp->next)
00289                 avp->next->prev = avp->prev;
00290         else
00291                 msg->avpList.tail = avp->prev;
00292         avp->next = avp->prev = 0;
00293 
00294         /* update short-cuts */
00295         switch (avp->code) {
00296                 case AVP_Session_Id: msg->sessionId = 0;break;
00297                 case AVP_Origin_Host: msg->orig_host = 0;break;
00298                 case AVP_Origin_Realm: msg->orig_realm = 0;break;
00299                 case AVP_Destination_Host: msg->dest_host = 0;break;
00300                 case AVP_Destination_Realm: msg->dest_realm = 0;break;
00301                 case AVP_Result_Code: msg->res_code = 0;break;
00302                 case AVP_Auth_Session_State: msg->auth_ses_state = 0;break;
00303         }
00304 
00305         return AAA_ERR_SUCCESS;
00306 }
00307 
00308 
00309 
00310 /* The function frees an AVP */
00311 AAAReturnCode  AAAFreeAVP(AAA_AVP **avp)
00312 {
00313         /* some checks */
00314         if (!avp || !(*avp)) {
00315                 LM_ERR("param avp cannot be null!!\n");
00316                 return AAA_ERR_PARAMETER;
00317         }
00318 
00319         /* free all the mem */
00320         if ( (*avp)->free_it && (*avp)->data.s )
00321                 ad_free((*avp)->data.s);
00322 
00323         ad_free( *avp );
00324         *avp = 0;
00325 
00326         return AAA_ERR_SUCCESS;
00327 }
00328 
00329 
00330 
00331 /* This function returns a pointer to the first AVP in the list */
00332 AAA_AVP*  AAAGetFirstAVP(AAA_AVP_LIST *avpList){
00333         return avpList->head;
00334 }
00335 
00336 
00337 
00338 /* This function returns a pointer to the last AVP in the list */
00339 AAA_AVP*  AAAGetLastAVP(AAA_AVP_LIST *avpList)
00340 {
00341         return avpList->tail;
00342 }
00343 
00344 
00345 
00346 
00347 /* This function returns a pointer to the next AVP in the list */
00348 AAA_AVP*  AAAGetNextAVP(AAA_AVP *avp)
00349 {
00350         return avp->next;
00351 }
00352 
00353 
00354 
00355 /* This function returns a pointer to the previous AVP in the list */
00356 AAA_AVP*  AAAGetPrevAVP(AAA_AVP *avp)
00357 {
00358         return avp->prev;
00359 }
00360 
00361 
00362 
00363 /* This function converts the data in the AVP to a format suitable for
00364  * log or display functions. */
00365 char*  AAAConvertAVPToString(AAA_AVP *avp, char *dest, unsigned int destLen)
00366 {
00367         int l;
00368         int i;
00369 
00370         if (!avp || !dest || !destLen) {
00371                 LM_ERR("param AVP, DEST or DESTLEN passed as null!!!\n");
00372                 return 0;
00373         }
00374         l = snprintf(dest,destLen,"AVP(%p < %p >%p):packetType=%u;code=%u,"
00375                 "flags=%x;\nDataType=%u;VendorID=%u;DataLen=%u;\n",
00376                 avp->prev,avp,avp->next,avp->packetType,avp->code,avp->flags,
00377                 avp->type,avp->vendorId,avp->data.len);
00378         switch(avp->type) {
00379                 case AAA_AVP_STRING_TYPE:
00380                         l+=snprintf(dest+l,destLen-l,"String: <%.*s>",avp->data.len,
00381                                 avp->data.s);
00382                         break;
00383                 case AAA_AVP_INTEGER32_TYPE:
00384                         l+=snprintf(dest+l,destLen-l,"Int32: <%u>(%x)",
00385                                 htonl(*((unsigned int*)avp->data.s)),
00386                                 htonl(*((unsigned int*)avp->data.s)));
00387                         break;
00388                 case AAA_AVP_ADDRESS_TYPE:
00389                         i = 1;
00390                         switch (avp->data.len) {
00391                                 case 4: i=i*0;
00392                                 case 6: i=i*2;
00393                                         l+=snprintf(dest+l,destLen-l,"Address IPv4: <%d.%d.%d.%d>",
00394                                                 (unsigned char)avp->data.s[i+0],
00395                                                 (unsigned char)avp->data.s[i+1],
00396                                                 (unsigned char)avp->data.s[i+2],
00397                                                 (unsigned char)avp->data.s[i+3]);
00398                                         break;
00399                                 case 16: i=i*0;
00400                                 case 18: i=i*2;
00401                                         l+=snprintf(dest+l,destLen-l,
00402                                                 "Address IPv6: <%x.%x.%x.%x.%x.%x.%x.%x>",
00403                                                 ((avp->data.s[i+0]<<8)+avp->data.s[i+1]),
00404                                                 ((avp->data.s[i+2]<<8)+avp->data.s[i+3]),
00405                                                 ((avp->data.s[i+4]<<8)+avp->data.s[i+5]),
00406                                                 ((avp->data.s[i+6]<<8)+avp->data.s[i+7]),
00407                                                 ((avp->data.s[i+8]<<8)+avp->data.s[i+9]),
00408                                                 ((avp->data.s[i+10]<<8)+avp->data.s[i+11]),
00409                                                 ((avp->data.s[i+12]<<8)+avp->data.s[i+13]),
00410                                                 ((avp->data.s[i+14]<<8)+avp->data.s[i+15]));
00411                                         break;
00412                         break;
00413                         }
00414                         break;
00415                 //case AAA_AVP_INTEGER64_TYPE:
00416                 case AAA_AVP_TIME_TYPE:
00417                 default:
00418                         LM_WARN("don't know how to print"
00419                                 " this data type [%d] -> trying hexa\n",avp->type);
00420                 case AAA_AVP_DATA_TYPE:
00421                         for (i=0;i<avp->data.len&&l<destLen-1;i++)
00422                         l+=snprintf(dest+l,destLen-l-1,"%x",
00423                                 ((unsigned char*)avp->data.s)[i]);
00424         }
00425         return dest;
00426 }
00427 
00428 
00429 
00430 AAA_AVP* AAACloneAVP( AAA_AVP *avp , unsigned char clone_data)
00431 {
00432         AAA_AVP *n_avp;
00433 
00434         if (!avp || !(avp->data.s) || !(avp->data.len) )
00435                 goto error;
00436 
00437         /* clone the avp structure */
00438         n_avp = (AAA_AVP*)ad_malloc( sizeof(AAA_AVP) );
00439         if (!n_avp) {
00440                 LM_ERR("cannot get free memory!!\n");
00441                 goto error;
00442         }
00443         memcpy( n_avp, avp, sizeof(AAA_AVP));
00444         n_avp->next = n_avp->prev = 0;
00445 
00446         if (clone_data) {
00447                 /* clone the avp data */
00448                 n_avp->data.s = (char*)ad_malloc( avp->data.len );
00449                 if (!(n_avp->data.s)) {
00450                         LM_ERR("cannot get free memory!!\n");
00451                         ad_free( n_avp );
00452                         goto error;
00453                 }
00454                 memcpy( n_avp->data.s, avp->data.s, avp->data.len);
00455                 n_avp->free_it = 1;
00456         } else {
00457                 /* link the clone's data to the original's data */
00458                 n_avp->data.s = avp->data.s;
00459                 n_avp->data.len = avp->data.len;
00460                 n_avp->free_it = 0;
00461         }
00462 
00463         return n_avp;
00464 error:
00465         return 0;
00466 }
00467 
00468 #endif