diam_message.c

Go to the documentation of this file.
00001 /*
00002  * $Id: diam_message.c 4516 2008-07-25 11:36:32Z osas $
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 
00028 /*! \file
00029  * \ingroup acc
00030  * \brief Acc:: Diameter messages
00031  *
00032  * - Module: \ref acc
00033  */
00034 
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 
00065 /*! \brief from a AAAMessage structure, a buffer to be send is build
00066  */
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 
00146 /*! \brief frees a message allocated through AAANewMessage()
00147  */
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 
00180 /*! \brief Sets the proper result_code into the Result-Code AVP; thus avp must already
00181  * exists into the reply message */
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 
00195 /*! \brief This function convert message to message structure */
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 
00329 /*! \brief print as debug all info contained by an aaa message + AVPs
00330  */
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

Generated on Tue May 22 16:00:26 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6