/* This function convert message to message structure */
AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
				 int attach_buf)
{
  unsigned char *ptr;
  AAAMessage    *msg;
  unsigned char version;
  unsigned int  msg_len;
  AAA_AVP       *avp;
  unsigned int  avp_code;
  unsigned char avp_flags;
  unsigned int  avp_len;
  unsigned int  avp_vendorID;
  unsigned int  avp_data_len;

  /* check the params */
  if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
    ERROR("ERROR:AAATranslateMessage: invalid buffered received!\n");
    goto error;
  }

  /* inits */
  msg = 0;
  avp = 0;
  ptr = source;

  /* alloc a new message structure */
  msg = (AAAMessage*)ad_malloc(sizeof(AAAMessage));
  if (!msg) {
    ERROR("ERROR:AAATranslateMessage: no more free memory!!\n");
    goto error;
  }
  memset(msg,0,sizeof(AAAMessage));

  /* get the version */
  version = (unsigned char)*ptr;
  ptr += VER_SIZE;
  if (version!=1) {
    ERROR("ERROR:AAATranslateMessage: invalid version [%d]in "
	  "AAA msg\n",version);
    goto error;
  }

  /* message length */
  msg_len = get_3bytes( ptr );
  ptr += MESSAGE_LENGTH_SIZE;
  if (msg_len>sourceLen) {
    ERROR("ERROR:AAATranslateMessage: AAA message len [%d] bigger then"
	  " buffer len [%d]\n",msg_len,sourceLen);
    goto error;
  }

  /* command flags */
  msg->flags = *ptr;
  ptr += FLAGS_SIZE;

  /* command code */
  msg->commandCode = get_3bytes( ptr );
  ptr += COMMAND_CODE_SIZE;

  /* application-Id */
  msg->applicationId = get_4bytes( ptr );
  ptr += APPLICATION_ID_SIZE;

  /* Hop-by-Hop-Id */
  msg->hopbyhopId = *((unsigned int*)ptr);
  ptr += HOP_BY_HOP_IDENTIFIER_SIZE;

  /* End-to-End-Id */
  msg->endtoendId = *((unsigned int*)ptr);
  ptr += END_TO_END_IDENTIFIER_SIZE;

  /* start decoding the AVPS */
  while (ptr < source+msg_len) {
    if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
      ERROR("ERROR:AAATranslateMessage: source buffer to short!! "
	    "Cannot read the whole AVP header!\n");
      goto error;
    }
    /* avp code */
    avp_code = get_4bytes( ptr );
    ptr += AVP_CODE_SIZE;
    /* avp flags */
    avp_flags = (unsigned char)*ptr;
    ptr += AVP_FLAGS_SIZE;
    /* avp length */
    avp_len = get_3bytes( ptr );
    ptr += AVP_LENGTH_SIZE;
    if (avp_len<1) {
      ERROR("ERROR:AAATranslateMessage: invalid AVP len [%d]\n",
	    avp_len);
      goto error;
    }
    /* avp vendor-ID */
    avp_vendorID = 0;
    if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
      avp_vendorID = get_4bytes( ptr );
      ptr += AVP_VENDOR_ID_SIZE;
    }
    /* data length */
    avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
    /*check the data length */
    if ( source+msg_len<ptr+avp_data_len) {
      ERROR("ERROR:AAATranslateMessage: source buffer to short!! "
	    "Cannot read a whole data for AVP!\n");
      goto error;
    }

    /* create the AVP */
    avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*)ptr,
			avp_data_len, AVP_DONT_FREE_DATA);
    if (!avp)
      goto error;

    /* link the avp into aaa message to the end */
    AAAAddAVPToMessage( msg, avp, msg->avpList.tail);

    ptr += to_32x_len( avp_data_len );
  }

  /* link the buffer to the message */
  if (attach_buf) {
    msg->buf.s = (char*)source;
    msg->buf.len = msg_len;
  }

  //AAAPrintMessage( msg );
  return  msg;
 error:
  ERROR("ERROR:AAATranslateMessage: message conversion droped!!\n");
  AAAFreeMessage(&msg);
  return 0;
}
Exemple #2
0
/**
 * Ungroup from a data buffer a list of avps
 * @param buf - payload to ungroup the list from
 * @returns the AAA_AVP_LIST or an empty one on error
 */
AAA_AVP_LIST AAAUngroupAVPS(str buf)
{
	char *ptr;
	AAA_AVP       *avp;
	unsigned int  avp_code;
	unsigned char avp_flags;
	unsigned int  avp_len;
	unsigned int  avp_vendorID;
	unsigned int  avp_data_len;
	AAA_AVP_LIST	lh;

	lh.head=0;
	lh.tail=0;
	ptr = buf.s;

	/* start decoding the AVPS */
	while (ptr < buf.s+buf.len) {
		if (ptr+AVP_HDR_SIZE(0x80)>buf.s+buf.len){
			LM_ERR("hss3g_ungroup_avps: source buffer to short!! "
					"Cannot read the whole AVP header!\n");
			goto error;
		}
		/* avp code */
		avp_code = get_4bytes( ptr );
		ptr += AVP_CODE_SIZE;
		/* avp flags */
		avp_flags = (unsigned char)*ptr;
		ptr += AVP_FLAGS_SIZE;
		/* avp length */
		avp_len = get_3bytes( ptr );
		ptr += AVP_LENGTH_SIZE;
		if (avp_len<1) {
			LM_ERR("hss3g_ungroup_avps: invalid AVP len [%d]\n",
					avp_len);
			goto error;
		}
		/* avp vendor-ID */
		avp_vendorID = 0;
		if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
			avp_vendorID = get_4bytes( ptr );
			ptr += AVP_VENDOR_ID_SIZE;
		}
		/* data length */
		avp_data_len = avp_len - AVP_HDR_SIZE(avp_flags);
		/*check the data length */
		if ( buf.s+buf.len<ptr+avp_data_len) {
			LM_ERR("hss3g_ungroup_avps: source buffer to short!! "
					"Cannot read a whole data for AVP!\n");
			goto error;
		}

		/* create the AVP */
		avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, ptr,
				avp_data_len, AVP_DONT_FREE_DATA);
		if (!avp) {
			LM_ERR("hss3g_ungroup_avps: can't create avp for member of list\n");
			goto error;
		}

		/* link the avp into aaa message to the end */
		avp->next = 0;
		avp->prev = lh.tail;
		if (lh.tail) {
			lh.tail->next=avp;
			lh.tail=avp;
		}
		else {
			lh.tail=avp;
			lh.head=avp;
		}

		ptr += to_32x_len( avp_data_len );
	}
	return lh;

error:
	LM_CRIT("AVP:<%.*s>\n",buf.len,buf.s);
	return lh;
}
Exemple #3
0
/** 
 * Receive Loop for Diameter messages.
 * Decodes the message and calls receive_message().
 * @param sock - the socket to receive from
 * @returns when the socket is closed
 */
void receive_loop(int sock)
{
	char buf[hdr_len],*msg;
	int buf_len,length,version,cnt,msg_len;
	AAAMessage *dmsg;
	
    while(!*shutdownx){
   		buf_len=0;
    	while(buf_len<1){	
    		cnt = select_recv(sock,buf+buf_len,1,0);
	    	if (cnt<0) goto error;
	    	buf_len+=cnt;
    	}
    	version = (unsigned char)buf[0];
    	if (version!=1) {
    		LOG(L_ERR,"ERROR:receive_loop():[%d] Recv Unknown version [%d]\n",sock,(unsigned char)buf[0]);
			continue;    		
    	}    	
    	while(buf_len<hdr_len){
	    	cnt = select_recv(sock,buf+buf_len,hdr_len-buf_len,0);
	    	if (cnt<0) goto error;
	    	buf_len+=cnt;
    	}
    	length = get_3bytes(buf+1);
    	if (length>DP_MAX_MSG_LENGTH){
			LOG(L_ERR,"ERROR:receive_loop():[%d] Msg too big [%d] bytes\n",sock,length);
			goto error;
    	}
    	LOG(L_DBG,"DBG:receive_loop():[%d] Recv Version %d Length %d\n",sock,version,length);
    	msg = shm_malloc(length);
    	if (!msg) {
    		LOG_NO_MEM("shm",length);
			goto error;
    	}
    		
    	memcpy(msg,buf,hdr_len);
    	msg_len=hdr_len;
    	while(msg_len<length){
    		cnt = select_recv(sock,msg+msg_len,length-msg_len,0);
	    	if (cnt<0) {
	    		shm_free(msg);
		    	goto error;
	    	}
    		msg_len+=cnt;
    	}
    	LOG(L_DBG,"DBG:receive_loop():[%d] Recv message complete\n",sock);
    	
    	dmsg = AAATranslateMessage((unsigned char*)msg,(unsigned int)msg_len,1);
    	
    	/*shm_free(msg);*/

		if (dmsg) receive_message(dmsg,sock);
		else{
			shm_free(msg);
		}
		
    }
error:
	if (this_peer) {
		if (this_peer->I_sock == sock) sm_process(this_peer,I_Peer_Disc,0,0,sock);
		if (this_peer->R_sock == sock) sm_process(this_peer,R_Peer_Disc,0,0,sock);
	}
    LOG(L_ERR,"INFO:receive_loop():[%d] Client closed connection or error... BYE\n",sock);
}
Exemple #4
0
/**
 * Does the actual receive operations on the Diameter TCP socket, for retrieving incoming messages.
 * The functions is to be called iteratively, each time there is something to be read from the TCP socket. It uses
 * a simple state machine to read first the version, then the header and then the rest of the message. When an
 * entire message is received, it is decoded and passed to the processing functions.
 * @param sp - the serviced peer to operate on
 * @return 1 on success, 0 on failure
 */
static inline int do_receive(serviced_peer_t *sp)
{
	int cnt,n,version;
	char *dst;
	AAAMessage *dmsg;

	switch (sp->state){
		case Receiver_Waiting:
			n = 1; /* wait for version */
			dst = sp->buf;
			break;

		case Receiver_Header:
			n = DIAMETER_HEADER_LEN - sp->buf_len; /* waiting for rest of header */
			dst = sp->buf+sp->buf_len;
			break;

		case Receiver_Rest_of_Message:
			n = sp->length - sp->msg_len;	/* waiting for the rest of the message */
			dst = sp->msg+sp->msg_len;
			break;

		default:
			LM_ERR("do_receive(): [%.*s] Unknown state %d\n",
					sp->p?sp->p->fqdn.len:0,
					sp->p?sp->p->fqdn.s:0,
					sp->state);
			goto error_and_reset;
	}

	cnt = recv(sp->tcp_socket,dst,n,0);

	if (cnt<=0)
		goto error_and_reset;

	switch (sp->state){
		case Receiver_Waiting:
			version = (unsigned char)(sp->buf[0]);
			if (version!=1) {
		  		LM_ERR("do_receive(): [%.*s] Received Unknown version [%d]\n",
		  				sp->p->fqdn.len,
		  				sp->p->fqdn.s,
		  				(unsigned char)sp->buf[0]);
				goto error_and_reset;
			}else{
				sp->state = Receiver_Header;
				sp->buf_len = 1;
			}
			break;

		case Receiver_Header:
			sp->buf_len+=cnt;
			if (sp->buf_len==DIAMETER_HEADER_LEN){
				sp->length = get_3bytes(sp->buf+1);
				if (sp->length>DP_MAX_MSG_LENGTH){
					LM_ERR("do_receive(): [%.*s] Msg too big [%d] bytes\n",
							sp->p?sp->p->fqdn.len:0,
							sp->p?sp->p->fqdn.s:0,
							sp->length);
					goto error_and_reset;
				}
				LM_DBG("receive_loop(): [%.*s] Recv Version %d Length %d\n",
						sp->p?sp->p->fqdn.len:0,
						sp->p?sp->p->fqdn.s:0,
						(unsigned char)(sp->buf[0]),
						sp->length);
				sp->msg = shm_malloc(sp->length);
				if (!sp->msg) {
					LOG_NO_MEM("shm",sp->length);
					goto error_and_reset;
				}

				memcpy(sp->msg,sp->buf,sp->buf_len);
				sp->msg_len=sp->buf_len;
				sp->state = Receiver_Rest_of_Message;
			}
			break;

		case Receiver_Rest_of_Message:
			sp->msg_len+=cnt;
			if (sp->msg_len==sp->length){
		    	dmsg = AAATranslateMessage((unsigned char*)sp->msg,(unsigned int)sp->msg_len,1);
				if (dmsg) {
					sp->msg = 0;
					receive_message(dmsg,sp);
				}
				else {
					shm_free(sp->msg);
					sp->msg = 0;
				}
				sp->msg_len = 0;
				sp->buf_len = 0;
				sp->state = Receiver_Waiting;
			}
			break;

		default:
			LM_ERR("do_receive(): [%.*s] Unknown state %d\n",
					sp->p?sp->p->fqdn.len:0,
					sp->p?sp->p->fqdn.s:0,
					sp->state);
			goto error_and_reset;
	}
	return 1;
error_and_reset:
	if (sp->msg){
		shm_free(sp->msg);
		sp->msg = 0;
		sp->msg_len = 0;
		sp->buf_len = 0;
		sp->state = Receiver_Waiting;
	}
	return 0;
}