diameter_msg.c

Go to the documentation of this file.
00001 
00054 #include "diameter.h"
00055 #include "diameter_api.h"
00056 
00057 
00058 #include <stdlib.h>
00059 #include <string.h>
00060 #include <netinet/in.h>
00061 
00062 #include "utils.h"
00063 #include "globals.h"
00064 
00065 #include "config.h"
00066 #include "peermanager.h"
00067 
00068 extern dp_config *config;   
00078 AAAReturnCode AAABuildMsgBuffer( AAAMessage *msg )
00079 {
00080     unsigned char *p;
00081     AAA_AVP       *avp;
00082 
00083     /* first let's comput the length of the buffer */
00084     msg->buf.len = AAA_MSG_HDR_SIZE; /* AAA message header size */
00085     /* count and add the avps */
00086     for(avp=msg->avpList.head;avp;avp=avp->next) {
00087         msg->buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
00088     }
00089 
00090     DBG("AAABuildMsgBuffer(): len=%d\n",msg->buf.len);
00091     /* allocate some memory */
00092     msg->buf.s = (char*)shm_malloc( msg->buf.len );
00093     if (!msg->buf.s) {
00094         LOG(L_ERR,"ERROR:AAABuildMsgBuffer: no more free memory!\n");
00095         goto error;
00096     }
00097     memset(msg->buf.s, 0, msg->buf.len);
00098 
00099     /* fill in the buffer */
00100     p = (unsigned char*)msg->buf.s;
00101     /* DIAMETER HEADER */
00102     /* message length */
00103     ((unsigned int*)p)[0] =htonl(msg->buf.len);
00104     /* Diameter Version */
00105     *p = 1;
00106     p += VER_SIZE + MESSAGE_LENGTH_SIZE;
00107     /* command code */
00108     ((unsigned int*)p)[0] = htonl(msg->commandCode);
00109     /* flags */
00110     *p = (unsigned char)msg->flags;
00111     p += FLAGS_SIZE + COMMAND_CODE_SIZE;
00112     /* application-ID */
00113     ((unsigned int*)p)[0] = htonl(msg->applicationId);
00114     p += APPLICATION_ID_SIZE;
00115     /* hop by hop id */
00116     ((unsigned int*)p)[0] = htonl(msg->hopbyhopId);
00117     p += HOP_BY_HOP_IDENTIFIER_SIZE;
00118     /* end to end id */
00119     ((unsigned int*)p)[0] = htonl(msg->endtoendId);
00120     p += END_TO_END_IDENTIFIER_SIZE;
00121 
00122     /* AVPS */
00123     for(avp=msg->avpList.head;avp;avp=avp->next) {
00124         /* AVP HEADER */
00125         /* avp code */
00126         set_4bytes(p,avp->code);
00127         p +=4;
00128         /* flags */
00129         (*p++) = (unsigned char)avp->flags;
00130         /* avp length */
00131         set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
00132         p += 3;
00133         /* vendor id */
00134         if ((avp->flags&0x80)!=0) {
00135             set_4bytes(p,avp->vendorId);
00136             p +=4;
00137         }
00138         /* data */
00139         memcpy( p, avp->data.s, avp->data.len);
00140         p += to_32x_len( avp->data.len );
00141     }
00142 
00143     if ((char*)p-msg->buf.s!=msg->buf.len) {
00144         LOG(L_ERR,"BUG: build_buf_from_msg: mismatch between len and buf!\n");
00145         shm_free( msg->buf.s );
00146         msg->buf.s = 0;
00147         msg->buf.len = 0;
00148         goto error;
00149     }
00150 
00151     return 1;
00152 error:
00153     return -1;
00154 }
00155 
00156 
00157 
00158 
00169 AAAMessage *AAANewMessage(
00170     AAACommandCode commandCode,
00171     AAAApplicationId applicationId,
00172     AAASessionId *sessionId,
00173     AAAMessage *request)
00174 {
00175     AAAMessage   *msg;
00176     AAA_AVP      *avp;
00177     AAA_AVP      *avp_t;
00178 #if 0
00179     unsigned int code;
00180 #endif
00181     str dest_host={"?",1};
00182     str dest_realm={"?",1};
00183 
00184     msg = 0;
00185 
00186     if (!sessionId||!sessionId->s) {
00187         if (request && request->sessionId){
00188             /* copy old session id */
00189             avp = request->sessionId;
00190             if (avp) {
00191                 sessionId = &(avp->data);
00192             }
00193         }else{
00194 //because of diameter base messages etc
00195 //          LOG(L_ERR,"ERROR:AAANewMessage: param session-ID received null and it's a request!!\n");
00196 //          goto error;
00197         }
00198     }
00199 
00200     /* allocated a new AAAMessage structure and set it to 0 */
00201     msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
00202     if (!msg) {
00203         LOG(L_ERR,"ERROR:AAANewMessage: no more free memory!!\n");
00204         goto error;
00205     }
00206     memset(msg,0,sizeof(AAAMessage));
00207 
00208     /* command code */
00209     msg->commandCode = commandCode;
00210     /* application ID */
00211     msg->applicationId = applicationId;
00212 
00213     /* add session ID */
00214     if (sessionId){
00215         avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len,
00216             AVP_DUPLICATE_DATA);
00217         if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) {
00218             LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Session-Id avp\n");
00219             if (avp) AAAFreeAVP( &avp );
00220             goto error;
00221         }
00222         msg->sessionId = avp;
00223     }
00224     
00225 
00226     /* add origin host AVP */
00227     /* changed by cristian to comply with rfc3588: 
00228      * 6.3.  Origin-Host AVP
00229      *
00230      *    The Origin-Host AVP (AVP Code 264) is of type
00231      *    DiameterIdentity... */
00232     avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len,
00233         AVP_DUPLICATE_DATA);
00234     if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
00235         LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Host avp\n");
00236         if (avp) AAAFreeAVP( &avp );
00237         goto error;
00238     }
00239     msg->orig_host = avp;
00240     /* add origin realm AVP */
00241     avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len,
00242         AVP_DUPLICATE_DATA);
00243     if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
00244         LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Realm avp\n");
00245         if (avp) AAAFreeAVP( &avp );
00246         goto error;
00247     }
00248     msg->orig_realm = avp;
00249 
00250     if (!request) {
00251         /* it's a new request -> set the flag */
00252         msg->flags = 0x80;
00253         /* keep track of the session -> SendMessage will need it! */
00254         msg->sId = sessionId;
00255     } else {
00256         /* it'a an answer -> it will have the same session Id */
00257         msg->sId = request->sId;
00258         /* link the incoming peer to the answer */
00259         msg->in_peer = request->in_peer;
00260         /* set the P flag as in request */
00261         msg->flags |= request->flags&0x40;
00262         
00263         msg->endtoendId = request->endtoendId;
00264         msg->hopbyhopId = request->hopbyhopId;
00265 
00266     /* Mirror the old originhost/realm to destinationhost/realm*/
00267     avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0);
00268     if (avp) dest_host = avp->data;
00269     /* add destination host and destination realm */
00270     avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
00271         dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
00272     if (!avp) {
00273         LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Host avp\n");
00274         return 0;
00275     }
00276     if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
00277         LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Host avp to message\n");
00278         AAAFreeAVP(&avp);
00279         return 0;
00280     }
00281     avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0);
00282     if (avp) dest_realm = avp->data;
00283 
00284     avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
00285         dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
00286     if (!avp) {
00287         LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Realm avp\n");
00288         return 0;
00289     }
00290     if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
00291         LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Realm avp to message\n");
00292         AAAFreeAVP(&avp);
00293         return 0;
00294     }       
00295 
00296 
00297         msg->res_code=0;
00298         /* mirror all the proxy-info avp in the same order */
00299         avp_t = request->avpList.head;
00300         while ( (avp_t=AAAFindMatchingAVP
00301         (request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) {
00302             if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp,
00303             msg->avpList.tail)!=AAA_ERR_SUCCESS )
00304                 goto error;
00305         }
00306     }
00307 
00308     return msg;
00309 error:
00310     LOG(L_ERR,"ERROR:AAANewMessage: failed to create a new AAA message!\n");
00311     AAAFreeMessage(&msg);
00312     return 0;
00313 }
00314 
00323 AAAMessage *AAACreateRequest(AAAApplicationId app_id,
00324                             AAACommandCode command_code,
00325                             AAAMsgFlag flags,
00326                             AAASessionId *sessId)
00327 {
00328     AAAMessage *msg;
00329     msg = AAANewMessage(command_code,app_id,sessId,0);
00330     if (!msg) return 0;
00331     msg->hopbyhopId = next_hopbyhop();
00332     msg->endtoendId = next_endtoend();
00333     msg->flags |= flags;    
00334     return msg;
00335 }
00336 
00342 AAAMessage *AAACreateResponse(AAAMessage *request)
00343 {
00344     AAAMessage *msg;
00345     msg = AAANewMessage(request->commandCode,request->applicationId,request->sId,request);
00346         
00347     return msg;
00348 }
00349 
00350 
00356 AAAReturnCode  AAAFreeAVPList(AAA_AVP_LIST *avpList)
00357 {
00358     AAA_AVP *avp_t;
00359     AAA_AVP *avp;
00360     /* free the avp list */
00361     avp = avpList->head;
00362     while (avp) {
00363         avp_t = avp;
00364         avp = avp->next;
00365         /*free the avp*/
00366         AAAFreeAVP(&avp_t);
00367     }
00368     avpList->head = 0;
00369     avpList->tail = 0;
00370     return AAA_ERR_SUCCESS;
00371 }
00372 
00378 AAAReturnCode  AAAFreeMessage(AAAMessage **msg)
00379 {
00380     LOG(L_DBG,"DBG:AAAFreeMessage: Freeing message (%p) %d\n",*msg,(*msg)->commandCode);
00381     /* param check */
00382     if (!msg || !(*msg))
00383         goto done;
00384 
00385     /* free the avp list */
00386     AAAFreeAVPList(&((*msg)->avpList));
00387 
00388     /* free the buffer (if any) */
00389     if ( (*msg)->buf.s )
00390         shm_free( (*msg)->buf.s );
00391 
00392     /* free the AAA msg */
00393     shm_free(*msg);
00394     *msg = 0;
00395 
00396 done:
00397     return AAA_ERR_SUCCESS;
00398 }
00399 
00407 AAAResultCode  AAASetMessageResultCode(
00408     AAAMessage *message,
00409     AAAResultCode resultCode)
00410 {
00411     if ( !is_req(message) && message->res_code) {
00412         *((unsigned int*)(message->res_code->data.s)) = htonl(resultCode);
00413         return AAA_ERR_SUCCESS;
00414     }
00415     return AAA_ERR_FAILURE;
00416 }
00417 
00418 
00419 
00428 AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
00429                                                             int attach_buf)
00430 {
00431     unsigned char *ptr;
00432     AAAMessage    *msg;
00433     unsigned char version;
00434     unsigned int  msg_len;
00435     AAA_AVP       *avp;
00436     unsigned int  avp_code;
00437     unsigned char avp_flags;
00438     unsigned int  avp_len;
00439     unsigned int  avp_vendorID;
00440     unsigned int  avp_data_len;
00441 
00442     /* check the params */
00443     if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
00444         LOG(L_ERR,"ERROR:AAATranslateMessage: invalid buffered received!\n");
00445         goto error;
00446     }
00447 
00448     /* inits */
00449     msg = 0;
00450     avp = 0;
00451     ptr = source;
00452 
00453     /* alloc a new message structure */
00454     msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
00455     if (!msg) {
00456         LOG(L_ERR,"ERROR:AAATranslateMessage: no more free memory!!\n");
00457         goto error;
00458     }
00459     memset(msg,0,sizeof(AAAMessage));
00460 
00461     /* get the version */
00462     version = (unsigned char)*ptr;
00463     ptr += VER_SIZE;
00464     if (version!=1) {
00465         LOG(L_ERR,"ERROR:AAATranslateMessage: invalid version [%d]in "
00466             "AAA msg\n",version);
00467         goto error;
00468     }
00469 
00470     /* message length */
00471     msg_len = get_3bytes( ptr );
00472     ptr += MESSAGE_LENGTH_SIZE;
00473     if (msg_len>sourceLen) {
00474         LOG(L_ERR,"ERROR:AAATranslateMessage: AAA message len [%d] bigger then"
00475             " buffer len [%d]\n",msg_len,sourceLen);
00476         goto error;
00477     }
00478 
00479     /* command flags */
00480     msg->flags = *ptr;
00481     ptr += FLAGS_SIZE;
00482 
00483     /* command code */
00484     msg->commandCode = get_3bytes( ptr );
00485     ptr += COMMAND_CODE_SIZE;
00486 
00487     /* application-Id */
00488     msg->applicationId = get_4bytes( ptr );
00489     ptr += APPLICATION_ID_SIZE;
00490 
00491     /* Hop-by-Hop-Id */
00492     msg->hopbyhopId = ntohl(*((unsigned int*)ptr));
00493     ptr += HOP_BY_HOP_IDENTIFIER_SIZE;
00494 
00495     /* End-to-End-Id */
00496     msg->endtoendId = ntohl(*((unsigned int*)ptr));
00497     ptr += END_TO_END_IDENTIFIER_SIZE;
00498 
00499     /* start decoding the AVPS */
00500     while (ptr < source+msg_len) {
00501         if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
00502             LOG(L_ERR,"ERROR:AAATranslateMessage: source buffer to short!! "
00503                 "Cannot read the whole AVP header!\n");
00504             goto error;
00505         }
00506         /* avp code */
00507         avp_code = get_4bytes( ptr );
00508         ptr += AVP_CODE_SIZE;
00509         /* avp flags */
00510         avp_flags = (unsigned char)*ptr;
00511         ptr += AVP_FLAGS_SIZE;
00512         /* avp length */
00513         avp_len = get_3bytes( ptr );
00514         ptr += AVP_LENGTH_SIZE;
00515         if (avp_len<1) {
00516             LOG(L_ERR,"ERROR:AAATranslateMessage: invalid AVP len [%d]\n",
00517                 avp_len);
00518             goto error;
00519         }
00520         /* avp vendor-ID */
00521         avp_vendorID = 0;
00522         if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
00523             avp_vendorID = get_4bytes( ptr );
00524             ptr += AVP_VENDOR_ID_SIZE;
00525         }
00526         /* data length */
00527         avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
00528         /*check the data length */
00529         if ( source+msg_len<ptr+avp_data_len) {
00530             LOG(L_ERR,"ERROR:AAATranslateMessage: source buffer to short!! "
00531                 "Cannot read a whole data for AVP!\n");
00532             goto error;
00533         }
00534 
00535         /* create the AVP */
00536         avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*) ptr,
00537             avp_data_len, AVP_DONT_FREE_DATA);
00538         if (!avp)
00539             goto error;
00540 
00541         /* link the avp into aaa message to the end */
00542         AAAAddAVPToMessage( msg, avp, msg->avpList.tail);
00543 
00544         ptr += to_32x_len( avp_data_len );
00545     }
00546 
00547     /* link the buffer to the message */
00548     if (attach_buf) {
00549         msg->buf.s = (char*) source;
00550         msg->buf.len = msg_len;
00551     }
00552 
00553     //AAAPrintMessage( msg );
00554     return  msg;
00555 error:
00556     LOG(L_ERR,"ERROR:AAATranslateMessage: message conversion droped!!\n");
00557     AAAFreeMessage(&msg);
00558     return 0;
00559 }
00560 
00561 
00562 
00568 void AAAPrintMessage( AAAMessage *msg)
00569 {
00570     char    buf[1024];
00571     AAA_AVP *avp;
00572 
00573     /* print msg info */
00574     DBG("DEBUG: AAA_MESSAGE - %p\n",msg);
00575     DBG("\tCode = %u\n",msg->commandCode);
00576     DBG("\tFlags = %x\n",msg->flags);
00577 
00578     /*print the AVPs */
00579     avp = msg->avpList.head;
00580     while (avp) {
00581         AAAConvertAVPToString(avp,buf,1024);
00582         DBG("\n%s\n",buf);
00583         avp=avp->next;
00584     }
00585 }
00586 
00587 
00588 

Generated on Sun Oct 12 04:10:21 2008 for Open IMS Core CSCFs by  doxygen 1.5.2