modules_k/auth_diameter/avp.c

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