/** * Create a Diameter Request. * @param app_id - application id to be set * @param command_code - the command code for this message * @param flags - flags to be set * @param sessId - session id to be set * @returns the AAAMessage* or NULL on error */ AAAMessage *AAACreateRequest(AAAApplicationId app_id, AAACommandCode command_code, AAAMsgFlag flags, AAASession *session) { AAAMessage *msg; AAA_AVP *avp; msg = AAANewMessage(command_code,app_id,session,0); if (!msg) return 0; msg->hopbyhopId = next_hopbyhop(); msg->endtoendId = next_endtoend(); msg->flags |= flags; if(session){ /* add destination host and destination realm */ if(session->dest_host.s){ avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0, session->dest_host.s,session->dest_host.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:AAACreateRequest: Failed creating Destination Host avp\n"); goto error; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:AAACreateRequest: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); goto error; } } if(session->dest_realm.s){ avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0, session->dest_realm.s,session->dest_realm.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:AAACreateRequest: Failed creating Destination Realm avp\n"); goto error; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:AAACreateRequest: Failed adding Destination Realm avp to message\n"); AAAFreeAVP(&avp); goto error; } } } return msg; error: AAAFreeMessage(&msg); return NULL; }
/* copies the Origin-Host AVP from the src message in a Destination-Host AVP in the dest message * copies the Origin-Realm AVP from the src message in a Destination-Realm AVP in the dest message * */ int dup_routing_avps(AAAMessage* src, AAAMessage *dest){ AAA_AVP * avp; str dest_host, dest_realm; if(!src) return 1; avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Host,0,AAA_FORWARD_SEARCH); if(avp && avp->data.s && avp->data.len) { LOG(L_DBG,"DBG:dup_routing_avps: Origin Host AVP present, duplicating %.*s\n", avp->data.len, avp->data.s); dest_host = avp->data; avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0, dest_host.s,dest_host.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:dup_routing_avps: Failed creating Destination Host avp\n"); goto error; } if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:dup_routing_avps: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); goto error; } } avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Realm,0,AAA_FORWARD_SEARCH); if(avp && avp->data.s && avp->data.len) { LOG(L_DBG,"DBG:dup_routing_avps: Origin Realm AVP present, duplicating %.*s\n", avp->data.len, avp->data.s); dest_realm = avp->data; avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0, dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:dup_routing_avps: Failed creating Destination Host avp\n"); goto error; } if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:dup_routing_avps: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); goto error; } } return 1; error: return 0; }
/* frees a message allocated through AAANewMessage() */ AAAReturnCode AAAFreeMessage(AAAMessage **msg) { AAA_AVP *avp_t; AAA_AVP *avp; /* param check */ if (!msg || !(*msg)) goto done; /* free the avp list */ avp = (*msg)->avpList.head; while (avp) { avp_t = avp; avp = avp->next; /*free the avp*/ AAAFreeAVP(&avp_t); } /* free the buffer (if any) */ if ( (*msg)->buf.s ) ad_free( (*msg)->buf.s ); /* free the AAA msg */ ad_free(*msg); msg = 0; done: return AAA_ERR_SUCCESS; }
AAAMessage *send_unknown_request_answer(AAAMessage *req) { AAAMessage *ans=0; char x[4]; AAA_AVP *avp; /* UAA header is created based on the UAR */ ans = AAANewMessage(req->commandCode,req->applicationId,0,req); if (!ans) return 0; set_4bytes(x,(unsigned int) DIAMETER_UNABLE_TO_COMPLY); avp = AAACreateAVP(AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR: Failed creating avp for result code\n"); AAAFreeMessage(&ans); return 0; } if (AAAAddAVPToMessage(ans,avp,ans->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR: Failed adding avp to message\n"); AAAFreeAVP(&avp); AAAFreeMessage(&ans); return 0; } return ans; }
/** * Accounting client: sends an ACR Event and returns answer * @param acr ACR with EVENT_RECORD Accounting-Record-Type * @param dlgid app-level session/dialog id * @param peer_fqdn FQDN of diameter peer to send message to * @return answer (ACA) or NULL if sending failed */ AAAMessage* AAAAcctCliEvent(AAAMessage* acr, str* dlgid, str* peer_fqdn) { // TODO: check acr has Accounting-Record-Type with EVENT_RECORD value AAAMessage* aca = 0; AAA_AVP *avp; AAAAcctSession* s = AAACreateAcctSession(peer_fqdn, dlgid); if (!s) return 0; // add Session-Id AVP avp = AAACreateAVP( 263, 0, 0, s->sID->s, s->sID->len, AVP_DUPLICATE_DATA); if ( !avp || AAAAddAVPToMessage(acr,avp,0)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAAAcctCliEvent: cannot create/add Session-Id avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } acr->sessionId = avp; acct_cli_sm_process(s, ACC_EV_EVENT, acr, aca, 0); AAADropAcctSession(s); // TODO: only drop if received successfull answer, otherwise need to buffer and follow Accounting client state machine... return aca; error: return 0; }
/* copies the Origin-Host AVP from the src message in a Destination-Host AVP in the dest message * copies the Origin-Realm AVP from the src message in a Destination-Realm AVP in the dest message * */ int dup_routing_avps(AAAMessage* src, AAAMessage *dest) { AAA_AVP * avp; str dest_realm; if (!src) return 1; /* Removed By Jason to facilitate use of Diameter clustering (MUX) in SLEE architecture (Realm-routing only) - TODO - check spec */ /*avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Host,0,AAA_FORWARD_SEARCH); if(avp && avp->data.s && avp->data.len) { LM_DBG("dup_routing_avps: Origin Host AVP present, duplicating %.*s\n", avp->data.len, avp->data.s); dest_host = avp->data; avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0, dest_host.s,dest_host.len,AVP_DUPLICATE_DATA); if (!avp) { LM_ERR("dup_routing_avps: Failed creating Destination Host avp\n"); goto error; } if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) { LM_ERR("dup_routing_avps: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); goto error; } }*/ avp = AAAFindMatchingAVP(src, src->avpList.head, AVP_Origin_Realm, 0, AAA_FORWARD_SEARCH); if (avp && avp->data.s && avp->data.len) { LM_DBG("dup_routing_avps: Origin Realm AVP present, duplicating %.*s\n", avp->data.len, avp->data.s); dest_realm = avp->data; avp = AAACreateAVP(AVP_Destination_Realm, AAA_AVP_FLAG_MANDATORY, 0, dest_realm.s, dest_realm.len, AVP_DUPLICATE_DATA); if (!avp) { LM_ERR("dup_routing_avps: Failed creating Destination Host avp\n"); goto error; } if (AAAAddAVPToMessage(dest, avp, dest->avpList.tail) != AAA_ERR_SUCCESS) { LM_ERR("dup_routing_avps: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); goto error; } } return 1; error: return 0; }
/** * Frees a AVP List and all the members * @param avpList - list to be freed * @returns AAA_ERR_SUCCESS */ AAAReturnCode AAAFreeAVPList(AAA_AVP_LIST *avpList) { AAA_AVP *avp_t; AAA_AVP *avp; /* free the avp list */ avp = avpList->head; while (avp) { avp_t = avp; avp = avp->next; /*free the avp*/ AAAFreeAVP(&avp_t); } avpList->head = 0; avpList->tail = 0; return AAA_ERR_SUCCESS; }
/** * Create and add an AVP to a Diameter message. * @param m - Diameter message to add to * @param d - the payload data * @param len - length of the payload data * @param avp_code - the code of the AVP * @param flags - flags for the AVP * @param vendorid - the value of the vendor id or 0 if none - Diameter base protocol * @param data_do - what to do with the data when done * @param func - the name of the calling function, for debugging purposes * @returns 1 on success or 0 on failure */ static inline int Rf_add_avp(AAAMessage *m,char *d,int len,int avp_code, int flags,int vendorid,int data_do,const char *func) { AAA_AVP *avp; if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC; avp = AAACreateAVP(avp_code,flags,vendorid,d,len,data_do); if (!avp) { LOG(L_ERR,"ERR: Failed creating avp\n"); return 0; } if ( AAAAddAVPToMessage(m,avp,m->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR: Failed adding avp to message\n"); AAAFreeAVP(&avp); return 0; } return 1; }
/** * Accounting client sends an ACR Stop and returns answer * @param acr ACR with STOP_RECORD Accounting-Record-Type * @param peer_fqdn FQDN of diameter peer * @param s pointer to existing session * @return answer (ACA) or NULL if sending failed */ AAAMessage* AAAAcctCliStop(AAAMessage* acr, str* peer_fqdn, AAAAcctSession *s) { // TODO: check acr has Accounting-Record-Type with STOP_RECORD value AAAMessage* aca = 0; AAA_AVP *avp; // add Session-Id AVP avp = AAACreateAVP( 263, 0, 0, s->sID->s, s->sID->len, AVP_DUPLICATE_DATA); if ( !avp || AAAAddAVPToMessage(acr,avp,0)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAAAcctCliEvent: cannot create/add Session-Id avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } acr->sessionId = avp; acct_cli_sm_process(s, ACC_EV_STOP, acr, aca, 0); return aca; error: return 0; }
/* * This function creates and submits diameter authentication request as per * draft-srinivas-aaa-basic-digest-00.txt. * Service type of the request is Authenticate-Only. * Returns: * 1 - success * -1 - error * */ int diameter_authorize(struct hdr_field* hdr, str* p_method, struct sip_uri uri, struct sip_uri ruri, unsigned int m_id, rd_buf_t* rb) { str method, user_name; AAAMessage *req; AAA_AVP *avp, *position; int name_flag, port_flag; dig_cred_t* cred; unsigned int tmp; user_name.s=0; /* fixes gcc 4.0 warning */ if ( !p_method ) { LOG(L_ERR, M_NAME":diameter_authorize(): Invalid parameter value\n"); return -1; } if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL) return -1; if(hdr && hdr->parsed) cred = &(((auth_body_t*)hdr->parsed)->digest); else cred = NULL; method = *p_method; if(!cred) { /* Username AVP */ user_name.len = uri.user.len + uri.host.len; if(user_name.len>0) { user_name.len += 2; user_name.s = (char*)ad_malloc(user_name.len*sizeof(char)); memset(user_name.s, 0, user_name.len); memcpy(user_name.s, uri.user.s, uri.user.len); if(uri.user.len>0) { memcpy(user_name.s+uri.user.len, "@", 1); memcpy(user_name.s+uri.user.len+1, uri.host.s, uri.host.len); } else memcpy(user_name.s, uri.host.s, uri.host.len); } if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_FREE_DATA)) == 0) { LOG(L_ERR,M_NAME":diameter_authorize(): no more free memory!\n"); if(user_name.len>0) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } else /* it is a SIP message with credentials */ { /* Add Username AVP */ if (cred->username.domain.len>0) { if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, cred->username.whole.s, cred->username.whole.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free " "memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } else { user_name.len = cred->username.user.len + cred->realm.len; if(user_name.len>0) { user_name.s = ad_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free " "memory\n"); goto error; } memcpy(user_name.s, cred->username.whole.s, cred->username.whole.len); if(cred->username.whole.len>0) { user_name.s[cred->username.whole.len] = '@'; memcpy(user_name.s + cred->username.whole.len + 1, cred->realm.s, cred->realm.len); } else memcpy(user_name.s, cred->realm.s, cred->realm.len); } if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_FREE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free " "memory!\n"); if(user_name.len>0) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } } /* SIP_MSGID AVP */ DBG("******* m_id=%d\n", m_id); tmp = m_id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), sizeof(m_id), AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_AUTHENTICATION, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, uri.host.s, uri.host.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } #ifdef DEBUG DBG("Destination Realm: %.*s\n", uri.host.len, uri.host.s); #endif if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* Resource AVP */ user_name.len = ruri.user.len + ruri.host.len + ruri.port.len + 2; user_name.s = (char*)ad_malloc(user_name.len*sizeof(char)); memset(user_name.s, 0, user_name.len); memcpy(user_name.s, ruri.user.s, ruri.user.len); name_flag= 0; if(ruri.user.s) { name_flag = 1; memcpy(user_name.s+ruri.user.len, "@", 1); } memcpy(user_name.s+ruri.user.len+name_flag, ruri.host.s, ruri.host.len); port_flag=0; if(ruri.port.s) { port_flag = 1; memcpy(user_name.s+ruri.user.len+ruri.host.len+1, ":", 1); } memcpy(user_name.s+ruri.user.len+ruri.host.len+name_flag+port_flag, ruri.port.s, ruri.port.len); #ifdef DEBUG DBG(M_NAME": AVP_Resource=%.*s\n", user_name.len, user_name.s); #endif if( (avp=AAACreateAVP(AVP_Resource, 0, 0, user_name.s, user_name.len, AVP_FREE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); if(user_name.s) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } if(cred) /* it is a SIP message with credentials */ { /* Response AVP */ if( (avp=AAACreateAVP(AVP_Response, 0, 0, hdr->body.s, hdr->body.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } position = AAAGetLastAVP(&(req->avpList)); if( AAAAddAVPToMessage(req, avp, position)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } /* Method AVP */ if( (avp=AAACreateAVP(AVP_Method, 0, 0, p_method->s, p_method->len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } position = AAAGetLastAVP(&(req->avpList)); if( AAAAddAVPToMessage(req, avp, position)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); goto error1; } } #ifdef DEBUG AAAPrintMessage(req); #endif /* build a AAA message buffer */ if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LOG(L_ERR, M_NAME":diameter_authorize(): failed to reconnect" " to Diameter client\n"); goto error; } } /* send the message to the DIAMETER CLIENT */ switch( tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, m_id) ) { case AAA_ERROR: /* a transmission error occurred */ LOG(L_ERR, M_NAME":diameter_authorize(): message sending to the" " DIAMETER backend authorization server failed\n"); goto error; case AAA_CONN_CLOSED: LOG(L_NOTICE, M_NAME":diameter_authorize(): connection to Diameter" " client closed.It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; case AAA_TIMEOUT: LOG(L_NOTICE,M_NAME":diameter_authorize(): no response received\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } AAAFreeMessage(&req); return 1; error1: AAAFreeAVP(&avp); error: AAAFreeMessage(&req); return -1; }
/** * Allocates a new AAAMessage. * @param commandCode - the command code for this message * @param applicationId - application id to be set * @param sessionId - session id to be set * @param request - if you want to create a response, put the request here. If you want a * request, call with NULL * @returns the AAAMessage* or NULL on error * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ */ AAAMessage *AAANewMessage( AAACommandCode commandCode, AAAApplicationId applicationId, AAASessionId *sessionId, AAAMessage *request) { AAAMessage *msg; AAA_AVP *avp; AAA_AVP *avp_t; #if 0 unsigned int code; #endif str dest_host={"?",1}; str dest_realm={"?",1}; msg = 0; if (!sessionId||!sessionId->s) { if (request && request->sessionId){ /* copy old session id */ avp = request->sessionId; if (avp) { sessionId = &(avp->data); } }else{ //because of diameter base messages etc // LOG(L_ERR,"ERROR:AAANewMessage: param session-ID received null and it's a request!!\n"); // goto error; } } /* allocated a new AAAMessage structure and set it to 0 */ msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage)); if (!msg) { LOG(L_ERR,"ERROR:AAANewMessage: no more free memory!!\n"); goto error; } memset(msg,0,sizeof(AAAMessage)); /* command code */ msg->commandCode = commandCode; /* application ID */ msg->applicationId = applicationId; /* add session ID */ if (sessionId){ avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len, AVP_DUPLICATE_DATA); if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Session-Id avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } msg->sessionId = avp; } /* add origin host AVP */ /* changed by cristian to comply with rfc3588: * 6.3. Origin-Host AVP * * The Origin-Host AVP (AVP Code 264) is of type * DiameterIdentity... */ avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len, AVP_DUPLICATE_DATA); if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Host avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } msg->orig_host = avp; /* add origin realm AVP */ avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len, AVP_DUPLICATE_DATA); if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Realm avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } msg->orig_realm = avp; if (!request) { /* it's a new request -> set the flag */ msg->flags = 0x80; /* keep track of the session -> SendMessage will need it! */ msg->sId = sessionId; } else { /* it'a an answer -> it will have the same session Id */ msg->sId = request->sId; /* link the incoming peer to the answer */ msg->in_peer = request->in_peer; /* set the P flag as in request */ msg->flags |= request->flags&0x40; /**/ msg->endtoendId = request->endtoendId; msg->hopbyhopId = request->hopbyhopId; /* Mirror the old originhost/realm to destinationhost/realm*/ avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0); if (avp) dest_host = avp->data; /* add destination host and destination realm */ avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0, dest_host.s,dest_host.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Host avp\n"); return 0; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Host avp to message\n"); AAAFreeAVP(&avp); return 0; } avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0); if (avp) dest_realm = avp->data; avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0, dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA); if (!avp) { LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Realm avp\n"); return 0; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Realm avp to message\n"); AAAFreeAVP(&avp); return 0; } msg->res_code=0; /* mirror all the proxy-info avp in the same order */ avp_t = request->avpList.head; while ( (avp_t=AAAFindMatchingAVP (request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) { if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp, msg->avpList.tail)!=AAA_ERR_SUCCESS ) goto error; } } return msg; error: LOG(L_ERR,"ERROR:AAANewMessage: failed to create a new AAA message!\n"); AAAFreeMessage(&msg); return 0; }
int acc_diam_request( struct sip_msg *req ) { int attr_cnt; int cnt; AAAMessage *send = NULL; AAA_AVP *avp; struct sip_uri puri; str *uri; int ret; int i; int status; char tmp[2]; unsigned int mid; attr_cnt = core2strar( req, val_arr, int_arr, type_arr ); /* last value is not used */ attr_cnt--; if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("failed to create new AAA request\n"); return -1; } /* AVP_ACCOUNTIG_RECORD_TYPE */ if( (status = diam_status(req, acc_env.code))<0) { LM_ERR("status unknown\n"); goto error; } tmp[0] = status+'0'; tmp[1] = 0; if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 1, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_MSGID AVP */ mid = req->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), sizeof(mid), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* also the extra attributes */ attr_cnt += extra2strar( dia_extra, req, val_arr, int_arr, type_arr); /* add attributes */ for(i=0; i<attr_cnt; i++) { if((avp=AAACreateAVP(diam_attrs[i], 0,0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } /* and the leg attributes */ if ( leg_info ) { cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1); do { for (i=0; i<cnt; i++) { if((avp=AAACreateAVP(diam_attrs[attr_cnt+i], 0, 0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } } while ( (cnt=legs2strar(leg_info,req,val_arr,int_arr, type_arr,0))!=0 ); } if (get_uri(req, &uri) < 0) { LM_ERR("failed to get uri, From/To URI not found\n"); goto error; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From/To URI\n"); goto error; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* prepare the message to be sent over the network */ if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } /* send the message to the DIAMETER client */ ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, req->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed.It will be " "reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != ACC_SUCCESS) { /* a transmission error occurred */ LM_ERR("message sending to the DIAMETER backend authorization " "server failed\n"); goto error; } AAAFreeMessage(&send); return 1; error: AAAFreeMessage(&send); return -1; }
int acc_diam_request( struct sip_msg *rq, struct hdr_field *to, str *phrase ) { str* val_arr[ALL_LOG_FMT_LEN+1]; str atr_arr[ALL_LOG_FMT_LEN+1]; int attr_cnt; AAAMessage *send = NULL; AAA_AVP *avp; int i; int dummy_len; str* user; str* realm; str user_name; str value; str *uri; struct sip_uri puri; struct to_body* from; int ret, free_user_name; int status; char tmp[2]; unsigned int mid; if (skip_cancel(rq)) return 1; attr_cnt=fmt2strar( DIAM_ACC_FMT, rq, to, phrase, &dummy_len, &dummy_len, val_arr, atr_arr); if (attr_cnt!=(sizeof(DIAM_ACC_FMT)-1)) { LOG(L_ERR, "ERROR: acc_diam_request: fmt2strar failed\n"); return -1; } if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) { LOG(L_ERR, "ERROR: acc_diam_request: new AAA message not created\n"); return -1; } /* AVP_ACCOUNTIG_RECORD_TYPE */ if( (status = diam_status(rq, phrase))<0) { LOG(L_ERR, "ERROR: acc_diam_request: status unknown\n"); goto error; } tmp[0] = status+'0'; tmp[1] = 0; if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 1, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_MSGID AVP */ DBG("**ACC***** m_id=%d\n", rq->id); mid = rq->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), sizeof(mid), AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR, M_NAME":diameter_authorize(): no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, M_NAME":diameter_authorize(): avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_STATUS avp */ if( (avp=AAACreateAVP(AVP_SIP_STATUS, 0, 0, phrase->s, phrase->len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_METHOD avp */ value = rq->first_line.u.request.method; if( (avp=AAACreateAVP(AVP_SIP_METHOD, 0, 0, value.s, value.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* Handle AVP_USER_NAME as a special case */ free_user_name = 0; user=cred_user(rq); /* try to take it from credentials */ if (user) { realm = cred_realm(rq); if (realm) { user_name.len = user->len+1+realm->len; user_name.s = pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "ERROR: acc_diam_request: no memory\n"); goto error; } memcpy(user_name.s, user->s, user->len); user_name.s[user->len] = '@'; memcpy(user_name.s+user->len+1, realm->s, realm->len); free_user_name = 1; } else { user_name.len = user->len; user_name.s = user->s; } } else { /* from from uri */ if (rq->from && (from=get_from(rq)) && from->uri.len) { if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) { LOG(L_ERR, "ERROR: acc_diam_request: Bad From URI\n"); goto error; } user_name.len = puri.user.len+1+puri.host.len; user_name.s = pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "ERROR: acc_diam_request: no memory\n"); goto error; } memcpy(user_name.s, puri.user.s, puri.user.len); user_name.s[puri.user.len] = '@'; memcpy(user_name.s+puri.user.len+1, puri.host.s, puri.host.len); free_user_name = 1; } else { user_name.len = na.len; user_name.s = na.s; } } if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, free_user_name?AVP_FREE_DATA:AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); if(free_user_name) pkg_free(user_name.s); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* Remaining attributes from diam_attr vector */ for(i=0; i<attr_cnt; i++) { if((avp=AAACreateAVP(diam_attr[i], 0,0, val_arr[i]->s, val_arr[i]->len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"ERROR: acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } } if (get_uri(rq, &uri) < 0) { LOG(L_ERR, "ERROR: acc_diam_request: From/To URI not found\n"); goto error; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "ERROR: acc_diam_request: Error parsing From/To URI\n"); goto error; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LOG(L_ERR,"acc_diam_request: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LOG(L_ERR, "acc_diam_request: avp not added \n"); AAAFreeAVP(&avp); goto error; } /* prepare the message to be sent over the network */ if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) { LOG(L_ERR, "ERROR: acc_diam_request: message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LOG(L_ERR, M_NAME":acc_diam_request: failed to reconnect" " to Diameter client\n"); goto error; } } /* send the message to the DIAMETER client */ ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, rq->id); if(ret == AAA_CONN_CLOSED) { LOG(L_NOTICE, M_NAME":acc_diam_request: connection to Diameter" " client closed.It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != ACC_SUCCESS) /* a transmission error occurred */ { LOG(L_ERR, M_NAME":acc_diam_request: message sending to the" " DIAMETER backend authorization server failed\n"); goto error; } AAAFreeMessage(&send); return 1; error: AAAFreeMessage(&send); return -1; }
/* it checks if a user is member of a group */ int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group) { str *grp, user_name, user, domain, uri; dig_cred_t* cred = 0; int hf_type; struct hdr_field* h; struct sip_uri puri; AAAMessage *req; AAA_AVP *avp; int ret; unsigned int tmp; grp = (str*)_group; /* via fixup */ hf_type = (int)(long)_hf; uri.s = 0; uri.len = 0; /* extract the uri according with the _hf parameter */ switch(hf_type) { case 1: /* Request-URI */ uri = *(GET_RURI(_m)); break; case 2: /* To */ if (get_to_uri(_m, &uri) < 0) { LM_ERR("failed to extract To\n"); return -2; } break; case 3: /* From */ if (get_from_uri(_m, &uri) < 0) { LM_ERR("failed to extract From URI\n"); return -3; } break; case 4: /* Credentials */ get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LM_ERR("no authorized credentials found " "(error in scripts)\n"); return -4; } } cred = &((auth_body_t*)(h->parsed))->digest; break; } if (hf_type != 4) { if (parse_uri(uri.s, uri.len, &puri) < 0) { LM_ERR("failed to parse URI\n"); return -5; } user = puri.user; domain = puri.host; } else { user = cred->username.user; domain = cred->realm; } /* user@domain mode */ if (use_domain) { user_name.s = 0; user_name.len = user.len + domain.len; if(user_name.len>0) { user_name.len++; user_name.s = (char*)pkg_malloc(user_name.len); if (!user_name.s) { LM_ERR("no pkg memory left\n"); return -6; } memcpy(user_name.s, user.s, user.len); if(user.len>0) { user_name.s[user.len] = '@'; memcpy(user_name.s + user.len + 1, domain.s, domain.len); } else memcpy(user_name.s, domain.s, domain.len); } } else user_name = user; if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("can't create new AAA message!\n"); return -1; } /* Username AVP */ if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s, user_name.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Usergroup AVP */ if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s, grp->len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* SIP_MSGID AVP */ LM_DBG("******* m_id=%d\n", _m->id); tmp = _m->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), sizeof(tmp), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* ServiceType AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } /* Destination-Realm AVP */ uri = *(GET_RURI(_m)); parse_uri(uri.s, uri.len, &puri); if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("no more pkg memory!\n"); goto error; } if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); goto error1; } #ifdef DEBUG AAAPrintMessage(req); #endif /* build a AAA message buffer */ if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed." "It will be reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != AAA_USER_IN_GROUP) { LM_ERR("message sending to the DIAMETER backend authorization server" "failed or user is not in group\n"); goto error; } AAAFreeMessage(&req); return 1; error1: AAAFreeAVP(&avp); error: AAAFreeMessage(&req); return -1; }
/** * Allocates a new AAAMessage. * @param commandCode - the command code for this message * @param applicationId - application id to be set * @param sessionId - session id to be set * @param request - if you want to create a response, put the request here. If you want a * request, call with NULL * @returns the AAAMessage* or NULL on error * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ */ AAAMessage *AAANewMessage( AAACommandCode commandCode, AAAApplicationId applicationId, AAASession *session, AAAMessage *request) { AAAMessage *msg; AAA_AVP *avp; AAA_AVP *avp_t; str *sessionId=0; #if 0 unsigned int code; #endif // str dest_host={"?",1}; str dest_realm={"?",1}; msg = 0; if (!session||!session->id.s) { if (request){ /* copy old session id from AVP */ if (request->sessionId) sessionId = &(request->sessionId->data); }else{ if (commandCode!=Code_DW) LM_DBG("AAANewMessage: param session received null and it's a request!!\n"); } }else{ sessionId = &(session->id); } /* allocated a new AAAMessage structure and set it to 0 */ msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage)); if (!msg) { LM_ERR("AAANewMessage: no more free memory!!\n"); goto error; } memset(msg,0,sizeof(AAAMessage)); /* command code */ msg->commandCode = commandCode; /* application ID */ msg->applicationId = applicationId; /*add session ID */ if (sessionId){ avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len, AVP_DUPLICATE_DATA); if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) { LM_ERR("AAANewMessage: cannot create/add Session-Id avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } msg->sessionId = avp; } /* add origin host AVP */ /* changed by cristian to comply with rfc3588: * 6.3. Origin-Host AVP * * The Origin-Host AVP (AVP Code 264) is of type * DiameterIdentity... */ avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len, AVP_DUPLICATE_DATA); if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LM_ERR("AAANewMessage: cannot create/add Origin-Host avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } msg->orig_host = avp; /* add origin realm AVP */ avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len, AVP_DUPLICATE_DATA); if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LM_ERR("AAANewMessage: cannot create/add Origin-Realm avp\n"); if (avp) AAAFreeAVP( &avp ); goto error; } msg->orig_realm = avp; if (!request) { /* it's a new request -> set the flag */ msg->flags = 0x80; } else { /* link the incoming peer to the answer */ msg->in_peer = request->in_peer; /* set the P flag as in request */ msg->flags |= request->flags&0x40; /**/ msg->endtoendId = request->endtoendId; msg->hopbyhopId = request->hopbyhopId; //TODO: aon:move this information in the AAASession structure, do not add these fields for if (msg->commandCode==Code_CE||msg->commandCode==Code_DP||msg->commandCode==Code_DW || msg->commandCode==Diameter_CCR || msg->commandCode==Diameter_RAR){ // Don't add Destination Host/Realm because some stacks are way to picky and will just refuse it }else{ /* Mirror the old originhost/realm to destinationhost/realm*/ //avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0); //if (avp) dest_host = avp->data; /* add destination host and destination realm */ //avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0, // dest_host.s,dest_host.len,AVP_DUPLICATE_DATA); //if (!avp) { // LM_ERR("ERR:AAANewMessage: Failed creating Destination Host avp\n"); // goto error; // } // if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { // LM_ERR("ERR:AAANewMessage: Failed adding Destination Host avp to message\n"); // AAAFreeAVP(&avp); // goto error; // } avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0); if (avp) dest_realm = avp->data; avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0, dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA); if (!avp) { LM_ERR("ERR:AAANewMessage: Failed creating Destination Realm avp\n"); goto error; } if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) { LM_ERR("ERR:AAANewMessage: Failed adding Destination Realm avp to message\n"); AAAFreeAVP(&avp); goto error; } } msg->res_code=0; /* mirror all the proxy-info avp in the same order */ avp_t = request->avpList.head; while ( (avp_t=AAAFindMatchingAVP (request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) { if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp, msg->avpList.tail)!=AAA_ERR_SUCCESS ) goto error; } } return msg; error: LM_ERR("AAANewMessage: failed to create a new AAA message!\n"); AAAFreeMessage(&msg); return 0; }