示例#1
0
static bool GetSha1ForFile( RageFileBasic &f, unsigned char *szHash )
{
	hash_state sha1e;
	sha1_init(&sha1e);

	int origpos = f.Tell();
	f.Seek(0);
	unsigned char buf[4096];
	int got = f.Read(buf, 4096);
	if ( got == -1 )
		return false;
	while (got > 0)
	{
		sha1_process(&sha1e, buf, got);
		got = f.Read(buf, 4096);
		if ( got == -1 )
			return false;
	}
	sha1_done(&sha1e, szHash);
	f.Seek(origpos);
	return true;
}
示例#2
0
文件: sha1.c 项目: MalaGaM/nxscripts
/**
  Self-test the hash
  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
int  sha1_test(void)
{
 #ifndef LTC_TEST
    return CRYPT_NOP;
 #else
  static const struct {
      char *msg;
      unsigned char hash[20];
  } tests[] = {
    { "abc",
      { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
        0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
        0x9c, 0xd0, 0xd8, 0x9d }
    },
    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
      { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
        0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
        0xE5, 0x46, 0x70, 0xF1 }
    }
  };

  int i;
  unsigned char tmp[20];
  hash_state md;

  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0]));  i++) {
      sha1_init(&md);
      sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
      sha1_done(&md, tmp);
      if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
         return CRYPT_FAIL_TESTVECTOR;
      }
  }
  return CRYPT_OK;
  #endif
}
示例#3
0
static void sha1_process_wrap( void *ctx, const unsigned char *data )
{
    sha1_process( (sha1_context *) ctx, data );
}
示例#4
0
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
 * calculate the session key using the diffie-hellman algorithm. Following
 * that, the session hash is calculated, and signed with RSA or DSS. The
 * result is sent to the client. 
 *
 * See the ietf-secsh-transport draft, section 6, for details */
static void send_msg_kexdh_reply(mp_int *dh_e) {

	mp_int dh_p, dh_q, dh_g, dh_y, dh_f;
	unsigned char randbuf[DH_P_LEN];
	int dh_q_len;
	hash_state hs;

	TRACE(("enter send_msg_kexdh_reply"));
	
	assert(ses.kexstate.recvkexinit);

	m_mp_init_multi(&dh_g, &dh_p, &dh_q, &dh_y, &dh_f, NULL);

	/* read the prime and generator*/
	if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN)
			!= MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	
	if (mp_set_int(&dh_g, dh_g_val) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* calculate q = (p-1)/2 */
	if (mp_sub_d(&dh_p, 1, &dh_y) != MP_OKAY) { /*dh_y is just a temp var here*/
		dropbear_exit("Diffie-Hellman error");
	}
	if (mp_div_2(&dh_y, &dh_q) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	dh_q_len = mp_unsigned_bin_size(&dh_q);

	/* calculate our random value dh_y */
	do {
		assert((unsigned int)dh_q_len <= sizeof(randbuf));
		genrandom(randbuf, dh_q_len);
		if (mp_read_unsigned_bin(&dh_y, randbuf, dh_q_len) != MP_OKAY) {
			dropbear_exit("Diffie-Hellman error");
		}
	} while (mp_cmp(&dh_y, &dh_q) == MP_GT || mp_cmp_d(&dh_y, 0) != MP_GT);

	/* f = g^y mod p */
	if (mp_exptmod(&dh_g, &dh_y, &dh_p, &dh_f) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	mp_clear(&dh_g);

	/* K = e^y mod p */
	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
	m_mp_init(ses.dh_K);
	if (mp_exptmod(dh_e, &dh_y, &dh_p, ses.dh_K) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* clear no longer needed vars */
	mp_clear_multi(&dh_y, &dh_p, &dh_q, NULL);

	/* Create the remainder of the hash buffer, to generate the exchange hash */
	/* K_S, the host key */
	buf_put_pub_key(ses.kexhashbuf, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey);
	/* e, exchange value sent by the client */
	buf_putmpint(ses.kexhashbuf, dh_e);
	/* f, exchange value sent by the server */
	buf_putmpint(ses.kexhashbuf, &dh_f);
	/* K, the shared secret */
	buf_putmpint(ses.kexhashbuf, ses.dh_K);

	/* calculate the hash H to sign */
	sha1_init(&hs);
	buf_setpos(ses.kexhashbuf, 0);
	sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
			ses.kexhashbuf->len);
	sha1_done(&hs, ses.hash);
	buf_free(ses.kexhashbuf);
	ses.kexhashbuf = NULL;
	
	/* first time around, we set the session_id to H */
	if (ses.session_id == NULL) {
		/* create the session_id, this never needs freeing */
		ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE);
		memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE);
	}
	
	/* we can start creating the kexdh_reply packet */
	CHECKCLEARTOWRITE();
	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
	buf_put_pub_key(ses.writepayload, ses.opts->hostkey,
			ses.newkeys->algo_hostkey);

	/* put f */
	buf_putmpint(ses.writepayload, &dh_f);
	mp_clear(&dh_f);

	/* calc the signature */
	buf_put_sign(ses.writepayload, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey, ses.hash, SHA1_HASH_SIZE);

	/* the SSH_MSG_KEXDH_REPLY is done */
	encrypt_packet();

	TRACE(("leave send_msg_kexdh_reply"));
}
示例#5
0
/* Generate the actual encryption/integrity keys, using the results of the
 * key exchange, as specified in section 5.2 of the IETF secsh-transport
 * draft. This occurs after the DH key-exchange.
 *
 * ses.newkeys is the new set of keys which are generated, these are only
 * taken into use after both sides have sent a newkeys message */
static void gen_new_keys() {

	unsigned char IV[MAX_IV_LEN];
	unsigned char key[MAX_KEY_LEN];
	hash_state hs;
	unsigned int keysize;

	TRACE(("enter gen_new_keys"));
	/* the dh_K and hash are the start of all hashes, we make use of that */
	sha1_init(&hs);
	sha1_process_mp(&hs, ses.dh_K);
	mp_clear(ses.dh_K);
	m_free(ses.dh_K);
	sha1_process(&hs, ses.hash, SHA1_HASH_SIZE);
	m_burn(ses.hash, SHA1_HASH_SIZE);

	/* client->server IV */
	hashkeys(IV, SHA1_HASH_SIZE, &hs, 'A');

	/* client->server encryption key */
	keysize = ses.newkeys->recv_algo_crypt->keysize;
	hashkeys(key, keysize, &hs, 'C');
	if (cbc_start(
			find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name),
			IV, key, keysize, 0, 
			&ses.newkeys->recv_symmetric_struct) != CRYPT_OK) {
		dropbear_exit("crypto error");
	}

	/* server->client IV */
	hashkeys(IV, SHA1_HASH_SIZE, &hs, 'B');

	/* server->client encryption key */
	keysize = ses.newkeys->trans_algo_crypt->keysize;
	hashkeys(key, keysize, &hs, 'D');
	if (cbc_start(
			find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name),
			IV, key, keysize, 0, 
			&ses.newkeys->trans_symmetric_struct) != CRYPT_OK) {
		dropbear_exit("crypto error");
	}
	/* MAC key client->server */
	keysize = ses.newkeys->recv_algo_mac->keysize;
	hashkeys(ses.newkeys->recvmackey, keysize, &hs, 'E');

	/* MAC key server->client */
	keysize = ses.newkeys->trans_algo_mac->keysize;
	hashkeys(ses.newkeys->transmackey, keysize, &hs, 'F');

#ifndef DISABLE_ZLIB
	gen_new_zstreams();
#endif
	
	/* Switch over to the new keys */
	m_burn(ses.keys, sizeof(struct key_context));
	m_free(ses.keys);
	ses.keys = ses.newkeys;
	ses.newkeys = NULL;

	TRACE(("leave gen_new_keys"));
}
示例#6
0
/* Pass len=0 to hash an entire file */
static int
process_file(hash_state *hs, const char *filename,
		unsigned int len, int prngd)
{
	static int already_blocked = 0;
	int readfd;
	unsigned int readcount;
	int ret = DROPBEAR_FAILURE;

#ifdef DROPBEAR_PRNGD_SOCKET
	if (prngd)
	{
		readfd = connect_unix(filename);
	}
	else
#endif
	{
		readfd = open(filename, O_RDONLY);
	}

	if (readfd < 0) {
		goto out;
	}

	readcount = 0;
	while (len == 0 || readcount < len)
	{
		int readlen, wantread;
		unsigned char readbuf[4096];
		if (!already_blocked && !prngd)
		{
			int res;
			struct timeval timeout;
			fd_set read_fds;

 			timeout.tv_sec  = 2;
 			timeout.tv_usec = 0;

			FD_ZERO(&read_fds);
			FD_SET(readfd, &read_fds);
			res = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
			if (res == 0)
			{
				dropbear_log(LOG_WARNING, "Warning: Reading the randomness source '%s' seems to have blocked.\nYou may need to find a better entropy source.", filename);
				already_blocked = 1;
			}
		}

		if (len == 0)
		{
			wantread = sizeof(readbuf);
		} 
		else
		{
			wantread = MIN(sizeof(readbuf), len-readcount);
		}

#ifdef DROPBEAR_PRNGD_SOCKET
		if (prngd)
		{
			char egdcmd[2];
			egdcmd[0] = 0x02;	/* blocking read */
			egdcmd[1] = (unsigned char)wantread;
			if (write(readfd, egdcmd, 2) < 0)
			{
				dropbear_exit("Can't send command to egd");
			}
		}
#endif

		readlen = read(readfd, readbuf, wantread);
		if (readlen <= 0) {
			if (readlen < 0 && errno == EINTR) {
				continue;
			}
			if (readlen == 0 && len == 0)
			{
				/* whole file was read as requested */
				break;
			}
			goto out;
		}
		sha1_process(hs, readbuf, readlen);
		readcount += readlen;
	}
	ret = DROPBEAR_SUCCESS;
out:
	close(readfd);
	return ret;
}
示例#7
0
/* Initialise the prng from /dev/urandom or prngd. This function can
 * be called multiple times */
void seedrandom() {
		
	hash_state hs;

	pid_t pid;
	struct timeval tv;
	clock_t clockval;

	/* hash in the new seed data */
	sha1_init(&hs);
	/* existing state */
	sha1_process(&hs, (void*)hashpool, sizeof(hashpool));

#ifdef DROPBEAR_PRNGD_SOCKET
	if (process_file(&hs, DROPBEAR_PRNGD_SOCKET, INIT_SEED_SIZE, 1) 
			!= DROPBEAR_SUCCESS) {
		dropbear_exit("Failure reading random device %s", 
				DROPBEAR_PRNGD_SOCKET);
	}
#else
	/* non-blocking random source (probably /dev/urandom) */
	if (process_file(&hs, DROPBEAR_URANDOM_DEV, INIT_SEED_SIZE, 0) 
			!= DROPBEAR_SUCCESS) {
		dropbear_exit("Failure reading random device %s", 
				DROPBEAR_URANDOM_DEV);
	}
#endif

	/* A few other sources to fall back on. 
	 * Add more here for other platforms */
#ifdef __linux__
	/* Seems to be a reasonable source of entropy from timers. Possibly hard
	 * for even local attackers to reproduce */
	process_file(&hs, "/proc/timer_list", 0, 0);
	/* Might help on systems with wireless */
	process_file(&hs, "/proc/interrupts", 0, 0);

	process_file(&hs, "/proc/loadavg", 0, 0);
	process_file(&hs, "/proc/sys/kernel/random/entropy_avail", 0, 0);

	/* Mostly network visible but useful in some situations.
	 * Limit size to avoid slowdowns on systems with lots of routes */
	process_file(&hs, "/proc/net/netstat", 4096, 0);
	process_file(&hs, "/proc/net/dev", 4096, 0);
	process_file(&hs, "/proc/net/tcp", 4096, 0);
	/* Also includes interface lo */
	process_file(&hs, "/proc/net/rt_cache", 4096, 0);
	process_file(&hs, "/proc/vmstat", 0, 0);
#endif

	pid = getpid();
	sha1_process(&hs, (void*)&pid, sizeof(pid));

	/* gettimeofday() doesn't completely fill out struct timeval on 
	   OS X (10.8.3), avoid valgrind warnings by clearing it first */
	memset(&tv, 0x0, sizeof(tv));
	gettimeofday(&tv, NULL);
	sha1_process(&hs, (void*)&tv, sizeof(tv));

	clockval = clock();
	sha1_process(&hs, (void*)&clockval, sizeof(clockval));

	/* When a private key is read by the client or server it will
	 * be added to the hashpool - see runopts.c */

	sha1_done(&hs, hashpool);

	counter = 0;
	donerandinit = 1;

	/* Feed it all back into /dev/urandom - this might help if Dropbear
	 * is running from inetd and gets new state each time */
	write_urandom();
}
示例#8
0
static bool CalculateMpqHashSha1(
    TMPQArchive * ha,
    PMPQ_SIGNATURE_INFO pSI,
    unsigned char * sha1_tail0,
    unsigned char * sha1_tail1,
    unsigned char * sha1_tail2)
{
    ULONGLONG BeginBuffer;
    hash_state sha1_state_temp;
    hash_state sha1_state;
    LPBYTE pbDigestBuffer = NULL;
    char szPlainName[MAX_PATH];

    // Allocate buffer for creating the MPQ digest.
    pbDigestBuffer = ALLOCMEM(BYTE, MPQ_DIGEST_UNIT_SIZE);
    if(pbDigestBuffer == NULL)
        return false;

    // Initialize SHA1 state structure
    sha1_init(&sha1_state);

    // Calculate begin of data to be hashed
    BeginBuffer = pSI->BeginMpqData;

    // Create the digest
    for(;;)
    {
        ULONGLONG BytesRemaining;
        DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE;

        // Check the number of bytes remaining
        BytesRemaining = pSI->EndMpqData - BeginBuffer;
        if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE)
            dwToRead = (DWORD)BytesRemaining;
        if(dwToRead == 0)
            break;

        // Read the next chunk 
        if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead))
        {
            FREEMEM(pbDigestBuffer);
            return false;
        }

        // Pass the buffer to the hashing function
        sha1_process(&sha1_state, pbDigestBuffer, dwToRead);

        // Move pointers
        BeginBuffer += dwToRead;
    }

    // Add all three known tails and generate three hashes
    memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
    sha1_done(&sha1_state_temp, sha1_tail0);

    memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
    GetPlainAnsiFileName(ha->pStream->szFileName, szPlainName);
    AddTailToSha1(&sha1_state_temp, szPlainName);
    sha1_done(&sha1_state_temp, sha1_tail1);

    memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
    AddTailToSha1(&sha1_state_temp, "ARCHIVE");
    sha1_done(&sha1_state_temp, sha1_tail2);

    // Finalize the MD5 hash
    FREEMEM(pbDigestBuffer);
    return true;
}
示例#9
0
文件: crypt3.cpp 项目: GetEnvy/Envy
void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt)
{
  byte AESKey[16],AESInit[16];

  bool Cached=false;
  for (uint I=0;I<ASIZE(KDF3Cache);I++)
    if (KDF3Cache[I].Pwd==*Password &&
        (Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL &&
        KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0))
    {
      memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey));
      memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit));
      Cached=true;
      break;
    }

  if (!Cached)
  {
    byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
    WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
    size_t RawLength=2*wcslen(PwdW);
    if (Salt!=NULL)
    {
      memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
      RawLength+=SIZE_SALT30;
    }
    sha1_context c;
    sha1_init(&c);

    const int HashRounds=0x40000;
    for (int I=0;I<HashRounds;I++)
    {
      sha1_process( &c, RawPsw, RawLength, false);
      byte PswNum[3];
      PswNum[0]=(byte)I;
      PswNum[1]=(byte)(I>>8);
      PswNum[2]=(byte)(I>>16);
      sha1_process( &c, PswNum, 3, false);
      if (I%(HashRounds/16)==0)
      {
        sha1_context tempc=c;
        uint32 digest[5];
        sha1_done( &tempc, digest, false);
        AESInit[I/(HashRounds/16)]=(byte)digest[4];
      }
    }
    uint32 digest[5];
    sha1_done( &c, digest, false);
    for (int I=0;I<4;I++)
      for (int J=0;J<4;J++)
        AESKey[I*4+J]=(byte)(digest[I]>>(J*8));

    KDF3Cache[KDF3CachePos].Pwd=*Password;
    if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true)
      memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30);
    memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey));
    memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit));
    KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache);

    cleandata(RawPsw,sizeof(RawPsw));
  }
示例#10
0
文件: sha1.c 项目: stevenberge/sha
/**
 * End of copied SHA1 code.
 *
 * ------------------------------------------------------------------------
 */
void  getDigest_1(void *digest,void *input,int len){
    struct sha1_state mystate;
    sha1_init(&mystate);
    sha1_process(&mystate,input,len);
    sha1_done(&mystate,digest);
}
示例#11
0
static void send_some_more_messages_normal (void)
{
	msg_t my_msg;
	struct iovec iov[2];
	int i;
	int send_now;
	size_t payload_size;
	hash_state sha1_hash;
	cs_error_t res;
	cpg_flow_control_state_t fc_state;
	int retries = 0;
	time_t before;

	if (cpg_fd < 0)
		return;

	send_now = my_msgs_to_send;

	//syslog (LOG_DEBUG,"%s() send_now:%d", __func__, send_now);
	my_msg.pid = my_pid;
	my_msg.nodeid = my_nodeid;
	payload_size = (rand() % 100000);
	my_msg.size = sizeof (msg_t) + payload_size;
	my_msg.seq = 0;
	for (i = 0; i < payload_size; i++) {
		buffer[i] = i;
	}
	sha1_init (&sha1_hash);
	sha1_process (&sha1_hash, buffer, payload_size);
	sha1_done (&sha1_hash, my_msg.sha1);

	iov[0].iov_len = sizeof (msg_t);
	iov[0].iov_base = &my_msg;
	iov[1].iov_len = payload_size;
	iov[1].iov_base = buffer;

	for (i = 0; i < send_now; i++) {
		if (in_cnchg && pcmk_test) {
			retries = 0;
			before = time(NULL);
			cs_repeat(retries, 30, res = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2));
			if (retries > 20) {
				syslog (LOG_ERR, "%s() -> cs_repeat: blocked for :%lu secs.",
					__func__, (unsigned long)(time(NULL) - before));
			}
			if (res != CS_OK) {
				syslog (LOG_ERR, "%s() -> cpg_mcast_joined error:%d.",
					__func__, res);
				return;
			}
		} else {
			res = cpg_flow_control_state_get (cpg_handle, &fc_state);
			if (res == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) {
				/* lets do this later */
				send_some_more_messages_later ();
				syslog (LOG_INFO, "%s() flow control enabled.", __func__);
				return;
			}

			res = cpg_mcast_joined (cpg_handle, CPG_TYPE_AGREED, iov, 2);
			if (res == CS_ERR_TRY_AGAIN) {
				/* lets do this later */
				send_some_more_messages_later ();
				if (i > 0) {
					syslog (LOG_INFO, "%s() TRY_AGAIN %d to send.",
						__func__, my_msgs_to_send);
				}
				return;
			} else if (res != CS_OK) {
				syslog (LOG_ERR, "%s() -> cpg_mcast_joined error:%d, exiting.",
					__func__, res);
				exit (-2);
			}
		}
		my_msgs_to_send--;
	}
}
示例#12
0
static void send_some_more_messages_zcb (void)
{
	msg_t *my_msg;
	int i;
	int send_now;
	size_t payload_size;
	size_t total_size;
	hash_state sha1_hash;
	cs_error_t res;
	cpg_flow_control_state_t fc_state;
	void *zcb_buffer;

	if (cpg_fd < 0)
		return;

	send_now = my_msgs_to_send;
	payload_size = (rand() % 100000);
	total_size = payload_size + sizeof (msg_t);
	cpg_zcb_alloc (cpg_handle, total_size, &zcb_buffer);

	my_msg = (msg_t*)zcb_buffer;

	//syslog (LOG_DEBUG,"%s() send_now:%d", __func__, send_now);
	my_msg->pid = my_pid;
	my_msg->nodeid = my_nodeid;
	my_msg->size = sizeof (msg_t) + payload_size;
	my_msg->seq = 0;
	for (i = 0; i < payload_size; i++) {
		my_msg->payload[i] = i;
	}
	sha1_init (&sha1_hash);
	sha1_process (&sha1_hash, my_msg->payload, payload_size);
	sha1_done (&sha1_hash, my_msg->sha1);

	for (i = 0; i < send_now; i++) {

		res = cpg_flow_control_state_get (cpg_handle, &fc_state);
		if (res == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) {
			/* lets do this later */
			send_some_more_messages_later ();
			syslog (LOG_INFO, "%s() flow control enabled.", __func__);
			goto free_buffer;
		}

		res = cpg_zcb_mcast_joined (cpg_handle, CPG_TYPE_AGREED, zcb_buffer, total_size);
		if (res == CS_ERR_TRY_AGAIN) {
			/* lets do this later */
			send_some_more_messages_later ();
//			if (i > 0) {
//				syslog (LOG_INFO, "%s() TRY_AGAIN %d to send.",
//					__func__, my_msgs_to_send);
//			}
			goto free_buffer;
		} else if (res != CS_OK) {
			syslog (LOG_ERR, "%s() -> cpg_mcast_joined error:%d, exiting.",
				__func__, res);
			exit (-2);
		}

		my_msgs_to_send--;
	}
free_buffer:
	cpg_zcb_free (cpg_handle, zcb_buffer);
}