message.c

Go to the documentation of this file.
00001 /*
00002  * $Id: message.c 2793 2007-09-20 07:47:17Z bogdan_iancu $
00003  *
00004  * 2003-04-07 created by bogdan
00005  *
00006  * Copyright (C) 2002-2003 FhG Fokus
00007  *
00008  * This file is part of disc, a free diameter server/client.
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 
00025 
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <sys/types.h>
00029 #include <netinet/in.h>
00030 
00031 
00032 #include "../../mem/shm_mem.h"
00033 #include "../../dprint.h"
00034 #include "diameter_msg.h"
00035 
00036 #define get_3bytes(_b) \
00037    ((((unsigned int)(_b)[0])<<16)|(((unsigned int)(_b)[1])<<8)|\
00038    (((unsigned int)(_b)[2])))
00039 
00040 #define get_4bytes(_b) \
00041    ((((unsigned int)(_b)[0])<<24)|(((unsigned int)(_b)[1])<<16)|\
00042    (((unsigned int)(_b)[2])<<8)|(((unsigned int)(_b)[3])))
00043 
00044 #define set_3bytes(_b,_v) \
00045    {(_b)[0]=((_v)&0x00ff0000)>>16;(_b)[1]=((_v)&0x0000ff00)>>8;\
00046    (_b)[2]=((_v)&0x000000ff);}
00047 
00048 #define set_4bytes(_b,_v) \
00049    {(_b)[0]=((_v)&0xff000000)>>24;(_b)[1]=((_v)&0x00ff0000)>>16;\
00050    (_b)[2]=((_v)&0x0000ff00)>>8;(_b)[3]=((_v)&0x000000ff);}
00051 
00052 #define to_32x_len( _len_ ) \
00053    ( (_len_)+(((_len_)&3)?4-((_len_)&3):0) )
00054 
00055 
00056 /* from a AAAMessage structure, a buffer to be send is build
00057  */
00058 AAAReturnCode AAABuildMsgBuffer( AAAMessage *msg )
00059 {
00060    unsigned char *p;
00061    AAA_AVP       *avp;
00062 
00063    /* first let's compute the length of the buffer */
00064    msg->buf.len = AAA_MSG_HDR_SIZE; /* AAA message header size */
00065    /* count and add the avps */
00066    for(avp=msg->avpList.head;avp;avp=avp->next) {
00067       msg->buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
00068    }
00069 
00070 // LM_DBG("xxxx len=%d\n",msg->buf.len);
00071    /* allocate some memory */
00072    msg->buf.s = (char*)ad_malloc( msg->buf.len );
00073    if (!msg->buf.s) {
00074       LM_ERR(" no more pkg memory!\n");
00075       goto error;
00076    }
00077    memset(msg->buf.s, 0, msg->buf.len);
00078 
00079    /* fill in the buffer */
00080    p = (unsigned char*)msg->buf.s;
00081    /* DIAMETER HEADER */
00082    /* message length */
00083    ((unsigned int*)p)[0] =htonl(msg->buf.len);
00084    /* Diameter Version */
00085    *p = 1;
00086    p += VER_SIZE + MESSAGE_LENGTH_SIZE;
00087    /* command code */
00088    ((unsigned int*)p)[0] = htonl(msg->commandCode);
00089    /* flags */
00090    *p = (unsigned char)msg->flags;
00091    p += FLAGS_SIZE + COMMAND_CODE_SIZE;
00092    /* application-ID */
00093    ((unsigned int*)p)[0] = htonl(msg->applicationId);
00094    p += APPLICATION_ID_SIZE;
00095    /* hop by hop id */
00096    ((unsigned int*)p)[0] = msg->hopbyhopId;
00097    p += HOP_BY_HOP_IDENTIFIER_SIZE;
00098    /* end to end id */
00099    ((unsigned int*)p)[0] = msg->endtoendId;
00100    p += END_TO_END_IDENTIFIER_SIZE;
00101 
00102    /* AVPS */
00103    for(avp=msg->avpList.head;avp;avp=avp->next) {
00104       /* AVP HEADER */
00105       /* avp code */
00106       set_4bytes(p,avp->code);
00107       p +=4;
00108       /* flags */
00109       (*p++) = (unsigned char)avp->flags;
00110       /* avp length */
00111       set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
00112       p += 3;
00113       /* vendor id */
00114       if ((avp->flags&0x80)!=0) {
00115          set_4bytes(p,avp->vendorId);
00116          p +=4;
00117       }
00118       /* data */
00119       memcpy( p, avp->data.s, avp->data.len);
00120       p += to_32x_len( avp->data.len );
00121    }
00122 
00123    if ((char*)p-msg->buf.s!=msg->buf.len) {
00124       LM_ERR("mismatch between len and buf!\n");
00125       ad_free( msg->buf.s );
00126       msg->buf.s = 0;
00127       msg->buf.len = 0;
00128       goto error;
00129    }
00130 // LM_DBG("Message: %.*s\n", msg->buf.len, msg->buf.s);
00131    return AAA_ERR_SUCCESS;
00132 error:
00133    return -1;
00134 }
00135 
00136 
00137 
00138 /* frees a message allocated through AAANewMessage()
00139  */
00140 AAAReturnCode  AAAFreeMessage(AAAMessage **msg)
00141 {
00142    AAA_AVP *avp_t;
00143    AAA_AVP *avp;
00144 
00145    /* param check */
00146    if (!msg || !(*msg))
00147       goto done;
00148 
00149    /* free the avp list */
00150    avp = (*msg)->avpList.head;
00151    while (avp) {
00152       avp_t = avp;
00153       avp = avp->next;
00154       /*free the avp*/
00155       AAAFreeAVP(&avp_t);
00156    }
00157 
00158    /* free the buffer (if any) */
00159    if ( (*msg)->buf.s )
00160       ad_free( (*msg)->buf.s );
00161 
00162    /* free the AAA msg */
00163    ad_free(*msg);
00164    msg = 0;
00165 
00166 done:
00167    return AAA_ERR_SUCCESS;
00168 }
00169 
00170 
00171 
00172 /* Sets the proper result_code into the Result-Code AVP; thus avp must already
00173  * exists into the reply message */
00174 AAAReturnCode  AAASetMessageResultCode(
00175    AAAMessage *message,
00176    AAAResultCode resultCode)
00177 {
00178    if ( !is_req(message) && message->res_code) {
00179       *((unsigned int*)(message->res_code->data.s)) = htonl(resultCode);
00180       return AAA_ERR_SUCCESS;
00181    }
00182    return AAA_ERR_FAILURE;
00183 }
00184 
00185 
00186 
00187 /* This function convert message to message structure */
00188 AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
00189                                              int attach_buf)
00190 {
00191    unsigned char *ptr;
00192    AAAMessage    *msg;
00193    unsigned char version;
00194    unsigned int  msg_len;
00195    AAA_AVP       *avp;
00196    unsigned int  avp_code;
00197    unsigned char avp_flags;
00198    unsigned int  avp_len;
00199    unsigned int  avp_vendorID;
00200    unsigned int  avp_data_len;
00201 
00202    /* check the params */
00203    if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
00204       LM_ERR(" invalid buffered received!\n");
00205       goto error;
00206    }
00207 
00208    /* inits */
00209    msg = 0;
00210    avp = 0;
00211    ptr = source;
00212 
00213    /* alloc a new message structure */
00214    msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
00215    if (!msg) {
00216       LM_ERR(" no more free memory!!\n");
00217       goto error;
00218    }
00219    memset(msg,0,sizeof(AAAMessage));
00220 
00221    /* get the version */
00222    version = (unsigned char)*ptr;
00223    ptr += VER_SIZE;
00224    if (version!=1) {
00225       LM_ERR(" invalid version [%d]in AAA msg\n",version);
00226       goto error;
00227    }
00228 
00229    /* message length */
00230    msg_len = get_3bytes( ptr );
00231    ptr += MESSAGE_LENGTH_SIZE;
00232    if (msg_len>sourceLen) {
00233       LM_ERR(" AAA message len [%d] bigger then"
00234          " buffer len [%d]\n",msg_len,sourceLen);
00235       goto error;
00236    }
00237 
00238    /* command flags */
00239    msg->flags = *ptr;
00240    ptr += FLAGS_SIZE;
00241 
00242    /* command code */
00243    msg->commandCode = get_3bytes( ptr );
00244    ptr += COMMAND_CODE_SIZE;
00245 
00246    /* application-Id */
00247    msg->applicationId = get_4bytes( ptr );
00248    ptr += APPLICATION_ID_SIZE;
00249 
00250    /* Hop-by-Hop-Id */
00251    msg->hopbyhopId = *((unsigned int*)ptr);
00252    ptr += HOP_BY_HOP_IDENTIFIER_SIZE;
00253 
00254    /* End-to-End-Id */
00255    msg->endtoendId = *((unsigned int*)ptr);
00256    ptr += END_TO_END_IDENTIFIER_SIZE;
00257 
00258    /* start decoding the AVPS */
00259    while (ptr < source+msg_len) {
00260       if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
00261          LM_ERR(" source buffer to short!! "
00262             "Cannot read the whole AVP header!\n");
00263          goto error;
00264       }
00265       /* avp code */
00266       avp_code = get_4bytes( ptr );
00267       ptr += AVP_CODE_SIZE;
00268       /* avp flags */
00269       avp_flags = (unsigned char)*ptr;
00270       ptr += AVP_FLAGS_SIZE;
00271       /* avp length */
00272       avp_len = get_3bytes( ptr );
00273       ptr += AVP_LENGTH_SIZE;
00274       if (avp_len<1) {
00275          LM_ERR(" invalid AVP len [%d]\n", avp_len);
00276          goto error;
00277       }
00278       /* avp vendor-ID */
00279       avp_vendorID = 0;
00280       if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
00281          avp_vendorID = get_4bytes( ptr );
00282          ptr += AVP_VENDOR_ID_SIZE;
00283       }
00284       /* data length */
00285       avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
00286       /*check the data length */
00287       if ( source+msg_len<ptr+avp_data_len) {
00288          LM_ERR(" source buffer to short!! "
00289             "Cannot read a whole data for AVP!\n");
00290          goto error;
00291       }
00292 
00293       /* create the AVP */
00294       avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*)ptr,
00295          avp_data_len, AVP_DONT_FREE_DATA);
00296       if (!avp)
00297          goto error;
00298 
00299       /* link the avp into aaa message to the end */
00300       AAAAddAVPToMessage( msg, avp, msg->avpList.tail);
00301 
00302       ptr += to_32x_len( avp_data_len );
00303    }
00304 
00305    /* link the buffer to the message */
00306    if (attach_buf) {
00307       msg->buf.s = (char*)source;
00308       msg->buf.len = msg_len;
00309    }
00310 
00311    //AAAPrintMessage( msg );
00312    return  msg;
00313 error:
00314    LM_ERR(" message conversion droped!!\n");
00315    AAAFreeMessage(&msg);
00316    return 0;
00317 }
00318 
00319 /* create a new minimal AAA message */
00320 AAAMessage* AAAInMessage(AAACommandCode commandCode, AAAApplicationId appId)
00321 {
00322    AAAMessage   *msg;
00323 
00324    /* we allocate a new AAAMessage structure and set it to 0 */
00325    msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
00326    if (!msg) 
00327    {
00328       LM_ERR("no more pkg memory!\n");
00329       return NULL;
00330    }
00331    memset(msg, 0, sizeof(AAAMessage));
00332 
00333    /* command code */
00334    msg->commandCode = commandCode;
00335 
00336    /* application ID */
00337    msg->applicationId = appId;
00338 
00339    /* it's a new request -> set the flag */
00340    msg->flags = 0x80;
00341 
00342    return msg;
00343 }
00344 
00345 
00346 /* print as debug all info contained by an aaa message + AVPs
00347  */
00348 void AAAPrintMessage( AAAMessage *msg)
00349 {
00350    char    buf[1024];
00351    AAA_AVP *avp;
00352 
00353    /* print msg info */
00354    LM_DBG("AAA_MESSAGE - %p\n",msg);
00355    LM_DBG("\tCode = %u\n",msg->commandCode);
00356    LM_DBG("\tFlags = %x\n",msg->flags);
00357 
00358    /*print the AVPs */
00359    avp = msg->avpList.head;
00360    while (avp) {
00361       AAAConvertAVPToString(avp,buf,1024);
00362       LM_DBG("\n%s\n",buf);
00363       avp=avp->next;
00364    }
00365 }

Generated on Wed May 23 20:00:27 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6