diam_message.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  *
00025  *   2003-04-07 created by bogdan
00026  */
00027 
00035 #ifdef DIAM_ACC
00036 
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <netinet/in.h>
00040 
00041 #include "../../mem/shm_mem.h"
00042 #include "../../dprint.h"
00043 #include "diam_message.h"
00044 
00045 #define get_3bytes(_b) \
00046         ((((unsigned int)(_b)[0])<<16)|(((unsigned int)(_b)[1])<<8)|\
00047         (((unsigned int)(_b)[2])))
00048 
00049 #define get_4bytes(_b) \
00050         ((((unsigned int)(_b)[0])<<24)|(((unsigned int)(_b)[1])<<16)|\
00051         (((unsigned int)(_b)[2])<<8)|(((unsigned int)(_b)[3])))
00052 
00053 #define set_3bytes(_b,_v) \
00054         {(_b)[0]=((_v)&0x00ff0000)>>16;(_b)[1]=((_v)&0x0000ff00)>>8;\
00055         (_b)[2]=((_v)&0x000000ff);}
00056 
00057 #define set_4bytes(_b,_v) \
00058         {(_b)[0]=((_v)&0xff000000)>>24;(_b)[1]=((_v)&0x00ff0000)>>16;\
00059         (_b)[2]=((_v)&0x0000ff00)>>8;(_b)[3]=((_v)&0x000000ff);}
00060 
00061 #define to_32x_len( _len_ ) \
00062         ( (_len_)+(((_len_)&3)?4-((_len_)&3):0) )
00063 
00064 
00067 AAAReturnCode AAABuildMsgBuffer( AAAMessage *msg )
00068 {
00069         char *p;
00070         AAA_AVP       *avp;
00071 
00072         /* first let's compute the length of the buffer */
00073         msg->buf.len = AAA_MSG_HDR_SIZE; /* AAA message header size */
00074         /* count and add the avps */
00075         for(avp=msg->avpList.head;avp;avp=avp->next) {
00076                 msg->buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
00077         }
00078 
00079         /* allocate some memory */
00080         msg->buf.s = (char*)ad_malloc( msg->buf.len );
00081         if (!msg->buf.s) {
00082                 LM_ERR("no more pkg free memory!\n");
00083                 goto error;
00084         }
00085         memset(msg->buf.s, 0, msg->buf.len);
00086 
00087         /* fill in the buffer */
00088         p = msg->buf.s;
00089         /* DIAMETER HEADER */
00090         /* message length */
00091         ((unsigned int*)p)[0] =htonl(msg->buf.len);
00092         /* Diameter Version */
00093         *p = 1;
00094         p += VER_SIZE + MESSAGE_LENGTH_SIZE;
00095         /* command code */
00096         ((unsigned int*)p)[0] = htonl(msg->commandCode);
00097         /* flags */
00098         *p = (unsigned char)msg->flags;
00099         p += FLAGS_SIZE + COMMAND_CODE_SIZE;
00100         /* application-ID */
00101         ((unsigned int*)p)[0] = htonl(msg->applicationId);
00102         p += APPLICATION_ID_SIZE;
00103         /* hop by hop id */
00104         ((unsigned int*)p)[0] = msg->hopbyhopId;
00105         p += HOP_BY_HOP_IDENTIFIER_SIZE;
00106         /* end to end id */
00107         ((unsigned int*)p)[0] = msg->endtoendId;
00108         p += END_TO_END_IDENTIFIER_SIZE;
00109 
00110         /* AVPS */
00111         for(avp=msg->avpList.head;avp;avp=avp->next) {
00112                 /* AVP HEADER */
00113                 /* avp code */
00114                 set_4bytes(p,avp->code);
00115                 p +=4;
00116                 /* flags */
00117                 (*p++) = (unsigned char)avp->flags;
00118                 /* avp length */
00119                 set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
00120                 p += 3;
00121                 /* vendor id */
00122                 if ((avp->flags&0x80)!=0) {
00123                         set_4bytes(p,avp->vendorId);
00124                         p +=4;
00125                 }
00126                 /* data */
00127                 memcpy( p, avp->data.s, avp->data.len);
00128                 p += to_32x_len( avp->data.len );
00129         }
00130 
00131         if ((char*)p-msg->buf.s!=msg->buf.len) {
00132                 LM_ERR("mismatch between len and buf!\n");
00133                 ad_free( msg->buf.s );
00134                 msg->buf.s = 0;
00135                 msg->buf.len = 0;
00136                 goto error;
00137         }
00138         LM_DBG("Message: %.*s\n", msg->buf.len, msg->buf.s);
00139         return AAA_ERR_SUCCESS;
00140 error:
00141         return -1;
00142 }
00143 
00144 
00145 
00148 AAAReturnCode  AAAFreeMessage(AAAMessage **msg)
00149 {
00150         AAA_AVP *avp_t;
00151         AAA_AVP *avp;
00152 
00153         /* param check */
00154         if (!msg || !(*msg))
00155                 goto done;
00156 
00157         /* free the avp list */
00158         avp = (*msg)->avpList.head;
00159         while (avp) {
00160                 avp_t = avp;
00161                 avp = avp->next;
00162                 /*free the avp*/
00163                 AAAFreeAVP(&avp_t);
00164         }
00165 
00166         /* free the buffer (if any) */
00167         if ( (*msg)->buf.s )
00168                 ad_free( (*msg)->buf.s );
00169 
00170         /* free the AAA msg */
00171         ad_free(*msg);
00172         msg = 0;
00173 
00174 done:
00175         return AAA_ERR_SUCCESS;
00176 }
00177 
00178 
00179 
00182 AAAResultCode  AAASetMessageResultCode(
00183         AAAMessage *message,
00184         AAAResultCode resultCode)
00185 {
00186         if ( !is_req(message) && message->res_code) {
00187                 *((unsigned int*)(message->res_code->data.s)) = htonl(resultCode);
00188                 return AAA_ERR_SUCCESS;
00189         }
00190         return AAA_ERR_FAILURE;
00191 }
00192 
00193 
00194 
00196 AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
00197                                                                                                                         int attach_buf)
00198 {
00199         unsigned char *ptr;
00200         AAAMessage    *msg;
00201         unsigned char version;
00202         unsigned int  msg_len;
00203         AAA_AVP       *avp;
00204         unsigned int  avp_code;
00205         unsigned char avp_flags;
00206         unsigned int  avp_len;
00207         unsigned int  avp_vendorID;
00208         unsigned int  avp_data_len;
00209 
00210         /* check the params */
00211         if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
00212                 LM_ERR("invalid buffered received!\n");
00213                 goto error;
00214         }
00215 
00216         /* inits */
00217         msg = 0;
00218         avp = 0;
00219         ptr = source;
00220 
00221         /* alloc a new message structure */
00222         msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
00223         if (!msg) {
00224                 LM_ERR("no more pkg free memory!!\n");
00225                 goto error;
00226         }
00227         memset(msg,0,sizeof(AAAMessage));
00228 
00229         /* get the version */
00230         version = (unsigned char)*ptr;
00231         ptr += VER_SIZE;
00232         if (version!=1) {
00233                 LM_ERR("invalid version [%d]in AAA msg\n",version);
00234                 goto error;
00235         }
00236 
00237         /* message length */
00238         msg_len = get_3bytes( ptr );
00239         ptr += MESSAGE_LENGTH_SIZE;
00240         if (msg_len>sourceLen) {
00241                 LM_ERR("AAA message len [%d] bigger then buffer len [%d]\n",
00242                                 msg_len,sourceLen);
00243                 goto error;
00244         }
00245 
00246         /* command flags */
00247         msg->flags = *ptr;
00248         ptr += FLAGS_SIZE;
00249 
00250         /* command code */
00251         msg->commandCode = get_3bytes( ptr );
00252         ptr += COMMAND_CODE_SIZE;
00253 
00254         /* application-Id */
00255         msg->applicationId = get_4bytes( ptr );
00256         ptr += APPLICATION_ID_SIZE;
00257 
00258         /* Hop-by-Hop-Id */
00259         msg->hopbyhopId = *((unsigned int*)ptr);
00260         ptr += HOP_BY_HOP_IDENTIFIER_SIZE;
00261 
00262         /* End-to-End-Id */
00263         msg->endtoendId = *((unsigned int*)ptr);
00264         ptr += END_TO_END_IDENTIFIER_SIZE;
00265 
00266         /* start decoding the AVPS */
00267         while (ptr < source+msg_len) {
00268                 if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
00269                         LM_ERR("source buffer to short!! "
00270                                 "Cannot read the whole AVP header!\n");
00271                         goto error;
00272                 }
00273                 /* avp code */
00274                 avp_code = get_4bytes( ptr );
00275                 ptr += AVP_CODE_SIZE;
00276                 /* avp flags */
00277                 avp_flags = (unsigned char)*ptr;
00278                 ptr += AVP_FLAGS_SIZE;
00279                 /* avp length */
00280                 avp_len = get_3bytes( ptr );
00281                 ptr += AVP_LENGTH_SIZE;
00282                 if (avp_len<1) {
00283                         LM_ERR("invalid AVP len [%d]\n", avp_len);
00284                         goto error;
00285                 }
00286                 /* avp vendor-ID */
00287                 avp_vendorID = 0;
00288                 if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
00289                         avp_vendorID = get_4bytes( ptr );
00290                         ptr += AVP_VENDOR_ID_SIZE;
00291                 }
00292                 /* data length */
00293                 avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
00294                 /*check the data length */
00295                 if ( source+msg_len<ptr+avp_data_len) {
00296                         LM_ERR("source buffer to short!! "
00297                                 "Cannot read a whole data for AVP!\n");
00298                         goto error;
00299                 }
00300 
00301                 /* create the AVP */
00302                 avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*)ptr,
00303                         avp_data_len, AVP_DONT_FREE_DATA);
00304                 if (!avp)
00305                         goto error;
00306 
00307                 /* link the avp into aaa message to the end */
00308                 AAAAddAVPToMessage( msg, avp, msg->avpList.tail);
00309 
00310                 ptr += to_32x_len( avp_data_len );
00311         }
00312 
00313         /* link the buffer to the message */
00314         if (attach_buf) {
00315                 msg->buf.s = (char*)source;
00316                 msg->buf.len = msg_len;
00317         }
00318 
00319         //AAAPrintMessage( msg );
00320         return  msg;
00321 error:
00322         LM_ERR("message conversion droped!!\n");
00323         AAAFreeMessage(&msg);
00324         return 0;
00325 }
00326 
00327 
00328 
00331 void AAAPrintMessage( AAAMessage *msg)
00332 {
00333         char    buf[1024];
00334         AAA_AVP *avp;
00335 
00336         /* print msg info */
00337         LM_DBG("AAA_MESSAGE - %p\n",msg);
00338         LM_DBG("\tCode = %u\n",msg->commandCode);
00339         LM_DBG("\tFlags = %x\n",msg->flags);
00340 
00341         /*print the AVPs */
00342         avp = msg->avpList.head;
00343         while (avp) {
00344                 AAAConvertAVPToString(avp,buf,1024);
00345                 LM_DBG("\n%s\n",buf);
00346                 avp=avp->next;
00347         }
00348 }
00349 
00350 AAAMessage* AAAInMessage(AAACommandCode cmdCode, 
00351                                 AAAApplicationId appID)
00352 {
00353         AAAMessage *msg;
00354 
00355         /* allocated a new AAAMessage structure a set it to 0 */
00356         msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
00357         if (!msg) {
00358                 LM_ERR("no more pkg free memory!\n");
00359                 return NULL;
00360         }
00361         memset(msg, 0, sizeof(AAAMessage));
00362 
00363         /* command code */
00364         msg->commandCode = cmdCode;
00365 
00366         /* application ID */
00367         msg->applicationId = appID;
00368 
00369         /* it's a new request -> set the flag */
00370         msg->flags = 0x80;
00371 
00372         return msg;
00373 }
00374 
00375 #endif