Exemple #1
0
int dcca_cb_put_value_to_avp(struct avp * msg, struct dict_object * avp, union avp_value * value)
{
    struct avp * a = NULL;

    CHECK_FCT( fd_msg_avp_new ( avp, 0, &a ) );
    CHECK_FCT( fd_msg_avp_setvalue( a, value ) );
    CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, a ) );

    return 0;
}
/* Perform a conversion between ipv6 in BCD to AVP served-party-ip-address */
int
s6a_add_ipv6_address (
  struct avp *avp,
  const char *ipv6_addr)
{
  struct avp                             *child_avp;
  union avp_value                         value;
  uint8_t                                 ipv6[18];
  struct in6_addr                         sin6;

  if (ipv6_addr == NULL) {
    return -1;
  }

  memset (&sin6, 0, sizeof (struct in6_addr));
  /*
   * This is an IPv6 family -> ipv6 buffer should start with 0x0002
   */
  ipv6[0] = 0x00;
  ipv6[1] = 0x02;

  if (inet_pton (AF_INET6, ipv6_addr, &sin6) == -1) {
    fprintf (stderr, "INET6 address conversion has failed\n");
    return -1;
  }

  /*
   * If the IPV6 address is 0:0:0:0:0:0:0:0 then we don't add it to the
   * * * * served-party ip address and consider the ip address can be dynamically
   * * * * allocated.
   */
  if (!IN6_IS_ADDR_UNSPECIFIED (sin6.s6_addr32)) {
    memcpy (&ipv6[2], &sin6.s6_addr, 16);
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_served_party_ip_addr, 0, &child_avp));
    value.os.data = ipv6;
    value.os.len = 18;
    CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
    CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
    return 0;
  }

  return -1;
}
/* Perform a conversion between ipv4 in BCD to AVP served-party-ip-address */
int
s6a_add_ipv4_address (
  struct avp *avp,
  const char *ipv4_addr)
{
  struct avp                             *child_avp;
  union avp_value                         value;
  uint8_t                                 ipv4[6];      /* Converted IPv4 address with family */
  in_addr_t                               sin;

  if (ipv4_addr == NULL) {
    return -1;
  }

  /*
   * This is an IPv4 family -> ipv4 buffer should start with 0x0001
   */
  ipv4[0] = 0x00;
  ipv4[1] = 0x01;
  sin = inet_addr (ipv4_addr);

  /*
   * No need to add the address if it is an any address
   */
  if (sin != INADDR_ANY) {
    memcpy (&ipv4[2], &sin, 4);
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_served_party_ip_addr, 0, &child_avp));
    value.os.data = ipv4;
    value.os.len = 6;
    CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
    CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
    return 0;
  }

  /*
   * No IP address added to AVP
   */
  return -1;
}
int
s6a_add_subscription_data_avp (
  struct msg *message,
  mysql_ul_ans_t * mysql_ans)
{
  int                                     ret = -1,
    i = 0;
  mysql_pdn_t                            *pdns = NULL;
  uint8_t                                 nb_pdns = 0;
  struct avp                             *avp = NULL,
    *child_avp = NULL;
  union avp_value                         value;

  if (mysql_ans == NULL) {
    return -1;
  }

  ret = hss_mysql_query_pdns (mysql_ans->imsi, &pdns, &nb_pdns);

  if (ret != 0) {
    /*
     * mysql query failed:
     * * * * - maybe no more memory
     * * * * - maybe user is not known (should have failed before)
     * * * * - maybe imsi has no EPS subscribed
     */
    goto out;
  }

  if (nb_pdns == 0) {
    /*
     * No PDN for this user -> DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION
     */
    return -1;
  }

  /*
   * Create the Subscription-Data AVP
   */
  CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_subscription_data, 0, &avp));
  {
    uint8_t                                 msisdn_len = strlen (mysql_ans->msisdn);

    /*
     * The MSISDN is known in the HSS, add it to the subscription data
     */
    if (msisdn_len > 0) {
      CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_msisdn, 0, &child_avp));
      value.os.data = (uint8_t *) mysql_ans->msisdn;
      value.os.len = msisdn_len;
      CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
      CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
    }
  }

  /*
   * We have to include the acess-restriction-data if the value stored in DB
   * * * * indicates that at least one restriction is applied to the USER.
   */
  if (mysql_ans->access_restriction != 0) {
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_access_restriction_data, 0, &child_avp));
    value.u32 = (uint32_t) mysql_ans->access_restriction;
    CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
    CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
  }

  /*
   * Add the Subscriber-Status to the list of AVP.
   * * * * It shall indicate if the service is barred or granted.
   * * * * TODO: normally this parameter comes from DB...
   */
  CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_subscriber_status, 0, &child_avp));
  /*
   * SERVICE_GRANTED
   */
  value.u32 = 0;
  CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
  CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
  /*
   * Add the Network-Access-Mode to the list of AVP.
   * * * * LTE Standalone HSS/MME: ONLY_PACKET.
   */
  CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_network_access_mode, 0, &child_avp));
  /*
   * SERVICE_GRANTED
   */
  value.u32 = 2;
  CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
  CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
  /*
   * Add the AMBR to list of AVPs
   */
  {
    struct avp                             *bandwidth;

    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_ambr, 0, &child_avp));
    /*
     * Uplink bandwidth
     */
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_max_bandwidth_ul, 0, &bandwidth));
    value.u32 = mysql_ans->aggr_ul;
    CHECK_FCT (fd_msg_avp_setvalue (bandwidth, &value));
    CHECK_FCT (fd_msg_avp_add (child_avp, MSG_BRW_LAST_CHILD, bandwidth));
    /*
     * Downlink bandwidth
     */
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_max_bandwidth_dl, 0, &bandwidth));
    value.u32 = mysql_ans->aggr_dl;
    CHECK_FCT (fd_msg_avp_setvalue (bandwidth, &value));
    CHECK_FCT (fd_msg_avp_add (child_avp, MSG_BRW_LAST_CHILD, bandwidth));
    CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
  }

  /*
   * Add the APN-Configuration-Profile only if at least one APN is subscribed
   */
  if (nb_pdns > 0) {
    struct avp                             *apn_profile;

    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_apn_configuration_profile, 0, &apn_profile));
    /*
     * Context-Identifier
     */
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_context_identifier, 0, &child_avp));
    value.u32 = 0;
    /*
     * TODO: this is the reference to the default APN...
     */
    CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
    CHECK_FCT (fd_msg_avp_add (apn_profile, MSG_BRW_LAST_CHILD, child_avp));
    /*
     * All-APN-Configurations-Included-Indicator
     */
    CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_all_apn_conf_inc_ind, 0, &child_avp));
    value.u32 = 0;
    CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
    CHECK_FCT (fd_msg_avp_add (apn_profile, MSG_BRW_LAST_CHILD, child_avp));

    for (i = 0; i < nb_pdns; i++) {
      struct avp                             *apn_configuration;
      mysql_pdn_t                            *pdn_elm;

      pdn_elm = &pdns[i];
      /*
       * APN-Configuration
       */
      CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_apn_configuration, 0, &apn_configuration));
      /*
       * Context-Identifier
       */
      CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_context_identifier, 0, &child_avp));
      value.u32 = i;
      CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
      CHECK_FCT (fd_msg_avp_add (apn_configuration, MSG_BRW_LAST_CHILD, child_avp));
      /*
       * PDN-Type
       */
      CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_pdn_type, 0, &child_avp));
      value.u32 = pdn_elm->pdn_type;
      CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
      CHECK_FCT (fd_msg_avp_add (apn_configuration, MSG_BRW_LAST_CHILD, child_avp));

      if ((pdn_elm->pdn_type == IPV4) || (pdn_elm->pdn_type == IPV4_OR_IPV6) || (pdn_elm->pdn_type == IPV4V6)) {
        s6a_add_ipv4_address (apn_configuration, pdn_elm->pdn_address.ipv4_address);
      }

      if ((pdn_elm->pdn_type == IPV6) || (pdn_elm->pdn_type == IPV4_OR_IPV6) || (pdn_elm->pdn_type == IPV4V6)) {
        s6a_add_ipv6_address (apn_configuration, pdn_elm->pdn_address.ipv6_address);
      }

      /*
       * Service-Selection
       */
      CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_service_selection, 0, &child_avp));
      value.os.data = (uint8_t *) pdn_elm->apn;
      value.os.len = strlen (pdn_elm->apn);
      CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
      CHECK_FCT (fd_msg_avp_add (apn_configuration, MSG_BRW_LAST_CHILD, child_avp));
      /*
       * Add the eps subscribed qos profile
       */
      {
        struct avp                             *qos_profile,
                                               *allocation_priority;

        CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_eps_subscribed_qos_profile, 0, &qos_profile));
        CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_qos_class_identifier, 0, &child_avp));
        /*
         * For a QCI_1
         */
        value.u32 = (uint32_t) pdn_elm->qci;
        CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
        CHECK_FCT (fd_msg_avp_add (qos_profile, MSG_BRW_LAST_CHILD, child_avp));
        /*
         * Allocation retention priority
         */
        {
          CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_allocation_retention_priority, 0, &allocation_priority));
          /*
           * Priority level
           */
          CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_priority_level, 0, &child_avp));
          value.u32 = (uint32_t) pdn_elm->priority_level;
          CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
          CHECK_FCT (fd_msg_avp_add (allocation_priority, MSG_BRW_LAST_CHILD, child_avp));
          /*
           * Pre-emption-capability
           */
          CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_pre_emption_capability, 0, &child_avp));
          value.u32 = (uint32_t) pdn_elm->pre_emp_cap;
          CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
          CHECK_FCT (fd_msg_avp_add (allocation_priority, MSG_BRW_LAST_CHILD, child_avp));
          /*
           * Pre-emption-vulnerability
           */
          CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_pre_emption_vulnerability, 0, &child_avp));
          value.u32 = (uint32_t) pdn_elm->pre_emp_vul;
          CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
          CHECK_FCT (fd_msg_avp_add (allocation_priority, MSG_BRW_LAST_CHILD, child_avp));
          CHECK_FCT (fd_msg_avp_add (qos_profile, MSG_BRW_LAST_CHILD, allocation_priority));
        }
        CHECK_FCT (fd_msg_avp_add (apn_configuration, MSG_BRW_LAST_CHILD, qos_profile));
      }
      /*
       * Add the AMBR to list of AVPs
       */
      {
        struct avp                             *bandwidth;

        CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_ambr, 0, &bandwidth));
        /*
         * Uplink bandwidth
         */
        CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_max_bandwidth_ul, 0, &child_avp));
        value.u32 = (uint32_t) pdn_elm->aggr_ul;
        CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
        CHECK_FCT (fd_msg_avp_add (bandwidth, MSG_BRW_LAST_CHILD, child_avp));
        /*
         * Downlink bandwidth
         */
        CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_max_bandwidth_dl, 0, &child_avp));
        value.u32 = (uint32_t) pdn_elm->aggr_dl;
        CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
        CHECK_FCT (fd_msg_avp_add (bandwidth, MSG_BRW_LAST_CHILD, child_avp));
        CHECK_FCT (fd_msg_avp_add (apn_configuration, MSG_BRW_LAST_CHILD, bandwidth));
      }
      CHECK_FCT (fd_msg_avp_add (apn_profile, MSG_BRW_LAST_CHILD, apn_configuration));
    }

    CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, apn_profile));
  }

  /*
   * Subscribed-Periodic-RAU-TAU-Timer
   */
  CHECK_FCT (fd_msg_avp_new (s6a_cnf.dataobj_s6a_subscribed_rau_tau_timer, 0, &child_avp));
  /*
   * Request an RAU/TAU update every x seconds
   */
  value.u32 = (uint32_t) mysql_ans->rau_tau;
  CHECK_FCT (fd_msg_avp_setvalue (child_avp, &value));
  CHECK_FCT (fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, child_avp));
  /*
   * Add the AVP to the message
   */
  CHECK_FCT (fd_msg_avp_add (message, MSG_BRW_LAST_CHILD, avp));
out:

  if (pdns) {
    free (pdns);
  }

  return ret;
}
Exemple #5
0
/* Callback for incoming Test-Request messages */
static int ta_tr_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
{
	struct msg *ans, *req;
    struct avp * src = NULL;
    struct avp_hdr * hdr = NULL;
    UsageServerSession* mi;
	
	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
	
	if (msg == NULL)
		return EINVAL;
	
	/* Value of Origin-Host */
    fprintf(stderr, "Request received from ");
    CHECK_FCT( fd_msg_search_avp ( *msg, ta_origin_host, &src) );
    if (src) {
        CHECK_FCT( fd_msg_avp_hdr( src, &hdr ) );
        fprintf(stderr, "'%.*s'", (int)hdr->avp_value->os.len, hdr->avp_value->os.data);
    } else {
        fprintf(stderr, "no_Origin-Host");
    }
    fprintf(stderr, ", replying...\n");
	
    //get or create the session/session state

    req = *msg;
	/* Create answer header */
	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
    ans = *msg;

    d_req_type reqType;

    //get the op type
    CHECK_FCT( fd_msg_search_avp ( req, ta_avp_optype, &src) );
    CHECK_FCT( fd_msg_avp_hdr( src, &hdr )  );
    reqType = hdr->avp_value->i32;
    if (reqType==d_start){
        //create the session state
        mi= usageserver_session_alloc();
        mi->leftQuota = DUMMY_INIT_QUOTA;
    }else{
        //get the session state
        fd_sess_state_retrieve(ta_cli_reg, sess, &mi);
    }

    if (reqType!=d_start){//for update, stop, need to update the leftQuota
        //update the left quota in session state, according to the used quota avp in req
        CHECK_FCT( fd_msg_search_avp ( req, ta_avp_usedQuota, &src) );
        CHECK_FCT( fd_msg_avp_hdr( src, &hdr )  );
        uint64_t usedQuota = hdr->avp_value->u64;
        if (mi->leftQuota>=usedQuota){
            mi->leftQuota-=usedQuota;
        }else{
            fprintf(stderr, "fatal, the used should not be larger then the granted last time.");
            mi->leftQuota=0;
        }
    }
    if (reqType!=d_stop){//for start, update, need to reply with grantedQuota
        //set the granted quota AVP according to requested quota and left quota in session state
        CHECK_FCT( fd_msg_search_avp ( req, ta_avp_requestQuota, &src) );
        CHECK_FCT( fd_msg_avp_hdr( src, &hdr )  );
        uint64_t reqAmt = hdr->avp_value->u64;
        uint64_t grantAmt=0;
        if (mi->leftQuota>=reqAmt){
            grantAmt = reqAmt;
        }else{
            grantAmt = mi->leftQuota;
        }
        hdr->avp_value->u64 = grantAmt;
        CHECK_FCT( fd_msg_avp_new ( ta_avp_grantedQuota, 0, &avp ) );
        CHECK_FCT( fd_msg_avp_setvalue( avp, hdr->avp_value ) );
        CHECK_FCT( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, avp ) );
        fprintf(stderr, "add granted quota avp, %llu.\n", grantAmt);
    }
    fprintf(stderr, "session:leftQuota:%llu\n", mi->leftQuota);
    
	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
	CHECK_FCT( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
    
    //save the session state
    fd_sess_state_store(ta_cli_reg, sess, &mi);
    
    /* Send the answer */
	CHECK_FCT( fd_msg_send( msg, NULL, NULL ) );

	return 0;
}
//Called to send a UAR
int test_sip_SAR_cb()
{
	struct dict_object * sar_model=NULL;
	struct msg * message=NULL;
	struct avp *avp=NULL;
	union avp_value value;
	
	//Fake values START
	char *sip_aor="sip:[email protected]";
	size_t aor_len=strlen(sip_aor); 
	char *destination_realm="tera.ics.keio.ac.jp";
	size_t destination_realmlen=strlen(destination_realm);
	char *destination_host="suika.tera.ics.keio.ac.jp";
	size_t destination_hostlen=strlen(destination_host);
	char *username="******";
	size_t usernamelen=strlen(username);
	char *sipserveruri="sip:[email protected]";
	size_t sipserverurilen=strlen(sipserveruri);
	// char *visitednetwork="Pink";
	//size_t visitednetworklen=strlen(visitednetwork);
	//int registrationtype = 2;
	int data_already_available=0;
	int assignment_type=0;
	//Fake values STOP
	
	//Create the base message for an RTR
	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Request", &sar_model, ENOENT) );
	CHECK_FCT( fd_msg_new (sar_model, 0, &message));
	
	
	
	// Create a new session 
	{
		CHECK_FCT( fd_msg_new_session( message, (os0_t)"appsip", CONSTSTRLEN("appsip") ) );
	}
	
	//Add the Auth-Application-Id 
	{
		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Application_Id, 0, &avp ) );
		value.i32 = 6;
		CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add ( message, MSG_BRW_LAST_CHILD, avp) );
	}	
	//Auth_Session_State
	{
		CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) );
		value.i32=1;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
	}
	
	//Origin_Host & Origin_Realm
	CHECK_FCT( fd_msg_add_origin ( message, 0 ));
	
	//Destination_Host
	{
		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) );
		value.os.data=(unsigned char *)destination_host;
		value.os.len=destination_hostlen;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
	}
	//Destination_Realm
	{
		CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Realm, 0, &avp ) );
		value.os.data=(unsigned char *)destination_realm;
		value.os.len=destination_realmlen;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
	}
	
	//SIP_AOR
	{
		
		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) );
		value.os.data=(unsigned char *)sip_aor;
		value.os.len=aor_len;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
		
	}
	//Username
	{
		
		CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) );
		value.os.data=(unsigned char *)username;
		value.os.len=usernamelen;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
		
	}
	//SIP_User_Data_Already_Available
	{
		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_User_Data_Already_Available, 0, &avp ) );
		value.i32=data_already_available;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
	}
	
	//SIP_Server_Assignment_Type;
	{
		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_Assignment_Type, 0, &avp ) );
		value.i32=assignment_type;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
	}
	//SIP_server_uri
	{
		
		CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Server_URI, 0, &avp ) );
		value.os.data=(unsigned char *)sipserveruri;
		value.os.len=sipserverurilen;
		CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) );
		CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) );
		
	}
	
	CHECK_FCT( fd_msg_send( &message, NULL, NULL ));
	
	return 0;
}
/* Callback for incoming Base Accounting Accounting-Request messages */
static int acct_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
{
	struct msg * m;
	struct avp * a = NULL;
	struct avp_hdr * art=NULL, *arn=NULL; /* We keep a pointer on the Accounting-Record-{Type, Number} AVPs from the query */
	struct acct_record_list rl;
	
	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
	if (msg == NULL)
		return EINVAL;
	
	m = *msg;
	
	/* Prepare a new record list */
	CHECK_FCT( acct_rec_prepare( &rl ) );
	
	/* Maps the AVPs from the query with this record list */
	CHECK_FCT( acct_rec_map( &rl, m ) );
	
	/* Check that at least one AVP was mapped */
	CHECK_FCT( acct_rec_validate( &rl ) );
	
	/* Now, save these mapped AVPs in the database */
	CHECK_FCT( acct_db_insert( &rl ) );
	
	acct_rec_empty( &rl );
	
	/* OK, we can send a positive reply now */
	
	/* Get Accounting-Record-{Number,Type} values */
	CHECK_FCT( fd_msg_search_avp ( m, acct_dict.Accounting_Record_Type, &a) );
	if (a) {
		CHECK_FCT( fd_msg_avp_hdr( a, &art )  );
	}
	CHECK_FCT( fd_msg_search_avp ( m, acct_dict.Accounting_Record_Number, &a) );
	if (a) {
		CHECK_FCT( fd_msg_avp_hdr( a, &arn )  );
	}
	
	/* Create the answer message */
	CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
	m = *msg;

	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
	CHECK_FCT( fd_msg_rescode_set( m, "DIAMETER_SUCCESS", NULL, NULL, 1 ) );
	
	/* Add the mandatory AVPs in the ACA */
	if (art) {
		CHECK_FCT( fd_msg_avp_new ( acct_dict.Accounting_Record_Type, 0, &a ) );
		CHECK_FCT( fd_msg_avp_setvalue( a, art->avp_value ) );
		CHECK_FCT( fd_msg_avp_add( m, MSG_BRW_LAST_CHILD, a ) );
	}
	if (arn) {
		CHECK_FCT( fd_msg_avp_new ( acct_dict.Accounting_Record_Number, 0, &a ) );
		CHECK_FCT( fd_msg_avp_setvalue( a, arn->avp_value ) );
		CHECK_FCT( fd_msg_avp_add( m, MSG_BRW_LAST_CHILD, a ) );
	}
	
	/* Send the answer */
	*act = DISP_ACT_SEND;
	return 0;
}