Hi all,
I'm trying to write a disk based HBcomm plug-in for heartbeat.
My current implementation is:
write:
write to it's own slot
sleep 0.2s
read:
scan all slots for new pkt
if (found) {
do {
read the slot for new pkt
} while (checksum of pkt is wrong)
} else {
sleep 0.1s
}
This plug-in suffers from packages losting as you can see. Using this
plug-in, heartbeat stops itself about 2 minutes after its starting, as it
finds more then 6 pkts missing.
Such a simple protocol is used because I failed to google out something
better. :(
You suggestions on how to improve are really appreciated. Thanks.
/*
* dskcm.c: Disk based communication code for heartbeat.
*
* Copyright (C) 2007 Xinwei Hu <[EMAIL PROTECTED]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 199309
#include <lha_internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <heartbeat.h>
#include <HBcomm.h>
#define PIL_PLUGINTYPE HB_COMM_TYPE
#define PIL_PLUGINTYPE_S HB_COMM_TYPE_S
#define PIL_PLUGIN dskcm
#define PIL_PLUGIN_S "dskcm"
#define PIL_PLUGINLICENSE LICENSE_LGPL
#define PIL_PLUGINLICENSEURL URL_LGPL
#include <pils/plugin.h>
/*
* The SHA implementation is from mozilla.
* TODO: reuse the code from HBauth
*
* The Original Code is SHA 180-1 Reference Implementation (Compact version)
*
* The Initial Developer of the Original Code is Paul Kocher of
* Cryptography Research. Portions created by Paul Kocher are
* Copyright (C) 1995-9 by Cryptography Research, Inc. All
* Rights Reserved.
*
* Contributor(s):
*
* Paul Kocher
*/
typedef struct {
unsigned int H[5];
unsigned int W[80];
int lenW;
unsigned int sizeHi,sizeLo;
} SHA_CTX;
static SHA_CTX sha_ctx;
static void SHA1_Init(SHA_CTX *ctx);
static void SHA1_Update(SHA_CTX *ctx, const void *dataIn, int len);
static void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx);
static void shaHashBlock(SHA_CTX *ctx);
#define DSKCM_ALIGN_SZ 512
#define DISKMETA_SZ DSKCM_ALIGN_SZ
#define SLOTMETA_SZ DSKCM_ALIGN_SZ
#define DSKCM_SLOT_SZ MAXMSG
#define DSKCM_MAX_SLOTS 64
#define DSKCM_VERSION 1
struct diskmeta
{
int32_t version;
int32_t slots;
int32_t slot_bitmap[4];
char padding[DISKMETA_SZ-24];
} __attribute__((__packed__));
struct slotmeta
{
int32_t gen_number;
int32_t seq_number;
int32_t chksum[5];
int32_t lrgn[64];
int32_t msg_size;
int32_t msg_cont;
char padding[SLOTMETA_SZ-292];
} __attribute__((__packed__));
struct slot
{
char msg[DSKCM_SLOT_SZ];
} __attribute__((__packed__));
static int is_valid_dev(const char* dev);
static void mysleep(double tm);
static void compute_chksum(char* msg, size_t msg_size, int32_t *sum);
static int check_chksum(char* msg, size_t msg_size, int32_t sum[5]);
static int dsk_slot_get(int dskfd, int slot, struct slot** sp, struct slotmeta** smp);
static int dsk_slot_set(int dskfd, int slot, struct slot* sp, struct slotmeta* smp);
static size_t dsk_read(int dskfd, int slot, void** rbuf);
static int dsk_write(int dskfd, int slot, const char* msg, size_t msg_size);
static size_t read_new_arrival(int dskfd, int slot, int* arri_slot, void** rbuf);
inline ssize_t dsk_get_impl(int dskfd, void** buf, size_t sz, off_t of);
//disk info
static int32_t dsk_max_slots;
static int32_t dsk_slot_start;
static int32_t dsk_slotmeta_start;
/* hua li de feng ge xian */
struct dskcm_private {
char* dskn;
int slot;
int dskfd;
};
static struct hb_media* dskcm_new(const char* dev, int slot);
static int dskcm_parse(const char* line);
static int dskcm_open(struct hb_media* mp);
static int dskcm_close(struct hb_media* mp);
static void* dskcm_read(struct hb_media* mp, int *lenp);
static int dskcm_write(struct hb_media* mp, void* msg, int len);
static int dskcm_descr(char** buffer);
static int dskcm_mtype(char** buffer);
static int dskcm_isping(void);
static struct hb_media_fns dskcmOps ={
NULL, /* Create single object function */
dskcm_parse, /* whole-line parse function */
dskcm_open,
dskcm_close,
dskcm_read,
dskcm_write,
dskcm_mtype,
dskcm_descr,
dskcm_isping,
};
PIL_PLUGIN_BOILERPLATE2("1.0", Debug)
static const PILPluginImports* PluginImports;
static PILPlugin* OurPlugin;
static PILInterface* OurInterface;
static struct hb_media_imports* OurImports;
static void* interfprivate;
/* XXX: why this ? */
static int
get_slot(const char* slot, int *s)
{
*s = (int)atoi(slot);
return 0;
}
#define LOG PluginImports->log
#define MALLOC PluginImports->alloc
#define STRDUP PluginImports->mstrdup
#define FREE PluginImports->mfree
PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports);
PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports)
{
/* Force the compiler to do a little type checking */
(void)(PILPluginInitFun)PIL_PLUGIN_INIT;
PluginImports = imports;
OurPlugin = us;
/* Register ourself as a plugin */
imports->register_plugin(us, &OurPIExports);
/* Register our interface implementation */
return imports->register_interface(us, PIL_PLUGINTYPE_S
, PIL_PLUGIN_S
, &dskcmOps
, NULL /*close */
, &OurInterface
, (void*)&OurImports
, interfprivate);
}
void mysleep(double tm)
{
double t = tm * 1000000;
if (random() % 2)
t += random() % 100000;
else
t -= random() % 100000;
usleep(t);
}
static void
compute_chksum(char* msg, size_t msg_size, int32_t *sum)
{
unsigned char hashout[20];
SHA1_Init(&sha_ctx);
SHA1_Update(&sha_ctx, msg, msg_size);
SHA1_Final(hashout, &sha_ctx);
memcpy(sum, hashout, sizeof(unsigned char)*20);
}
static int
check_chksum(char* msg, size_t msg_size, int32_t sum[5])
{
int32_t r[5];
compute_chksum(msg, msg_size, r);
if (memcmp(r, sum, sizeof(r)) == 0)
return 0;
else
return -1;
}
int is_valid_dev(const char* dev)
{
int dskfd = -1;
void* vp;
size_t sz;
ssize_t rsz;
int ri;
int i;
sz = DISKMETA_SZ > SLOTMETA_SZ ? DISKMETA_SZ : SLOTMETA_SZ;
sz = sz > DSKCM_SLOT_SZ ? sz : DSKCM_SLOT_SZ;
dskfd = open(dev, O_RDWR | O_DIRECT);
if (dskfd == -1) {
perror("open(main)");
return -1;
}
ri = posix_memalign(&vp,
DSKCM_ALIGN_SZ,
sz);
if (ri != 0) {
fprintf(stderr,
"posix_memalign(check_dsk): %d\n", ri);
return -1;
}
memset(vp, 0, sz);
rsz = pread(dskfd, (struct diskmeta*)vp, sizeof(struct diskmeta), 0);
if (rsz == -1) {
perror("pread(init_dsk)");
free(vp);
return -1;
}
if (((struct diskmeta*)vp)->version != DSKCM_VERSION) {
printf("This version of disk is not supported\n");
printf("Please re-initialize the disk.\n");
free(vp);
return -1;
}
i = ((struct diskmeta*)vp)->slots;
if (i <= 0 || i > DSKCM_MAX_SLOTS) {
printf("Wrong number of slots.\n");
printf("Please re-initialize the disk.\n");
free(vp);
return -1;
}
dsk_max_slots = i;
dsk_slotmeta_start = DISKMETA_SZ;
dsk_slot_start = DISKMETA_SZ + SLOTMETA_SZ * dsk_max_slots;
rsz = pread(dskfd, vp, DSKCM_SLOT_SZ, dsk_slot_start+DSKCM_SLOT_SZ*(i-1));
if (rsz == -1) {
perror("pread last slot(check_dsk)");
free(vp);
return -1;
}
free(vp);
return 0;
}
#define ISDSKCMOBJECT(mp) ((mp) && ((mp)->vf == (void*)&dskcmOps))
#define DSKCMASSERT(mp) g_assert(ISDSKCMOBJECT(mp))
static int
dskcm_mtype(char** buffer) {
*buffer = STRDUP(PIL_PLUGIN_S);
if (!*buffer) {
return 0;
}
return STRLEN_CONST(PIL_PLUGIN_S);
}
static int
dskcm_descr(char **buffer) {
const char constret[] = "Disk based broadcast";
*buffer = STRDUP(constret);
if (!*buffer) {
return 0;
}
return STRLEN_CONST(constret);
}
static int
dskcm_isping(void) {
return 0;
}
/*
* Open UDP/IP broadcast heartbeat interface
*/
static int
dskcm_open(struct hb_media* mp)
{
struct dskcm_private * dpi;
DSKCMASSERT(mp);
dpi = (struct dskcm_private*) mp->pd;
if ((dpi->dskfd = open(dpi->dskn, O_RDWR | O_DIRECT)) < 0) {
return HA_FAIL;
}
PILCallLog(LOG, PIL_INFO
, "Disk based broadcasting started on device %s slot %d."
, dpi->dskn, dpi->slot);
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG
, "dskcm_open : fd %d opened for reading/writing"
, dpi->dskfd);
}
return(HA_OK);
}
static int
dskcm_close(struct hb_media* mp)
{
struct dskcm_private * dpi;
int rc = HA_OK;
DSKCMASSERT(mp);
dpi = (struct dskcm_private *) mp->pd;
if (dpi->dskfd >= 0) {
if (close(dpi->dskfd) < 0) {
rc = HA_FAIL;
}
}
PILCallLog(LOG, PIL_INFO
, "Disk based broadcast heartbeat closed on device %s slot %d - Status: %d"
, dpi->dskn, dpi->slot, rc);
return(rc);
}
inline ssize_t
dsk_get_impl(int dskfd, void** buf, size_t sz, off_t of)
{
int ri;
ssize_t rsz;
void* rp;
*buf = 0;
ri = posix_memalign(&rp, DSKCM_ALIGN_SZ, sz);
if (ri != 0) {
fprintf(stderr, "posix_memalign(dsk_get_impl): %d\n", ri);
return -1;
}
rsz = pread(dskfd, rp, sz, of);
if (rsz == -1) {
perror("pread(dsk_get_imple)");
free(rp);
return -1;
}
*buf = rp;
return rsz;
}
int
dsk_slot_get(int dskfd, int slot, struct slot** sp, struct slotmeta** smp)
{
struct slot* rsp = NULL;
struct slotmeta* rsmp = NULL;
ssize_t rsz;
if (slot < 0 || slot >= dsk_max_slots)
return -1;
rsz = dsk_get_impl(dskfd, (void**)&rsp, sizeof(struct slot),
dsk_slot_start + DSKCM_SLOT_SZ * slot);
if (rsz == -1) {
perror("dsk_get_impl(dsk_slot_get)");
goto errout;
}
rsz = dsk_get_impl(dskfd, (void**)&rsmp, sizeof(struct slotmeta),
dsk_slotmeta_start + SLOTMETA_SZ*slot);
if (rsz == -1) {
perror("dsk_get_impl(dsk_get_imple)");
goto errout;
}
*sp = rsp;
*smp = rsmp;
return 0;
errout:
if (rsp) free(rsp);
if (rsmp) free(rsmp);
*sp = NULL; *smp = NULL;
return -1;
}
static size_t
dsk_read(int dskfd, int slot, void** rbuf)
{
struct slot* sp;
struct slotmeta* smp;
char *msg = NULL;
size_t size = 0;
int cont = 0;
int32_t seq_number = -1;
int32_t gen_number = 0;
int ri;
do {
ri = dsk_slot_get(dskfd, slot, &sp, &smp);
if (ri != 0) { //failed to read disk
PILCallLog(LOG, PIL_CRIT
, "Error preading disk: %s"
, strerror(errno));
if (msg != NULL) free(msg);
*rbuf = NULL;
return -1;
}
// print_chksum("dsk_read", smp->chksum);
if (gen_number == 0) {
gen_number = smp->gen_number;
} else if (gen_number != smp->gen_number) {
if (seq_number <= 0) {
// we are waiting for the first segment, but missed it.
// skip that and start to waiting for next pkt.
seq_number = -1;
gen_number = smp->gen_number;
} else {
// we are in the half way receiving a pkt
// give up.
PILCallLog(LOG, PIL_CRIT
, "Sending too fast. expect %d, get %d"
, gen_number, smp->gen_number);
free(msg); msg = NULL;
free(sp); free(smp);
return -1;
}
}
if (seq_number == -1)
seq_number = smp->seq_number;
else if (seq_number == smp->seq_number) {
free(sp); free(smp);
cont = 1;
continue;
}
if (check_chksum(sp->msg, smp->msg_size, smp->chksum) < 0) {
free(sp); free(smp);
cont = 1;
continue;
} else {
size += smp->msg_size;
if (msg == NULL) {
msg = malloc(sizeof(char) * size);
memset(msg, 0, sizeof(char) * size);
} else {
msg = realloc(msg, sizeof(char) * size);
memset(msg + size - smp->msg_size, 0, sizeof(char)*smp->msg_size);
}
if (msg == NULL) {
free(sp);
free(smp);
*rbuf = NULL;
return 0;
}
memcpy(msg + size - smp->msg_size, sp->msg, smp->msg_size);
if (smp->msg_cont == 1)
cont = 1;
else
cont = 0;
free(sp); free(smp);
}
if (cont == 1) {
PILCallLog(LOG, PIL_CRIT
, "We should never meet so big pkt!");
}
} while (cont);
*rbuf = msg;
return size;
}
static size_t
read_new_arrival(int dskfd, int slot, int* arri_slot, void** rbuf)
{
int i = 0;
static int lrgn_init = 0;
static int32_t lrgn[64];
static struct slotmeta* smps = NULL;
if (lrgn_init == 0 ) {
struct slotmeta* smp;
struct slot* sp;
int ri;
ri = dsk_slot_get(dskfd, slot, &sp, &smp);
if (ri != 0) {
PILCallLog(LOG, PIL_CRIT
, "Error get slot from disk: %s"
, strerror(errno));
return -1;
}
memcpy(lrgn, smp->lrgn, sizeof(int32_t)*64);
free(smp);
free(sp);
lrgn_init = 1;
}
if (smps == NULL) {
int ri;
ri = posix_memalign((void**)&smps,
DSKCM_ALIGN_SZ,
sizeof(struct slotmeta) * dsk_max_slots);
if (ri != 0) {
PILCallLog(LOG, PIL_CRIT
, "Error allocing aligned memory: %s"
, strerror(ri));
*rbuf = NULL;
return -1;
}
}
for (;;) {
size_t rsz;
rsz = pread(dskfd, smps, sizeof(struct slotmeta) * dsk_max_slots,
dsk_slotmeta_start);
if (rsz == -1) {
PILCallLog(LOG, PIL_CRIT
, "Error preading disk: %s"
, strerror(errno));
*rbuf = NULL;
return -1;
}
for (i = 0; i < dsk_max_slots; i++) {
if ((smps+i)->gen_number > lrgn[i]) {
lrgn[i] = (smps+i)->gen_number;
*arri_slot = i;
return dsk_read(dskfd, i, rbuf);
}
}
mysleep(0.1);
}
*rbuf = NULL;
return 0;
}
int
dsk_slot_set(int dskfd, int slot, struct slot* sp, struct slotmeta* smp)
{
ssize_t rsz;
if (slot < 0 || slot >= DSKCM_MAX_SLOTS)
return -1;
rsz = pwrite(dskfd, sp, sizeof(struct slot),
dsk_slot_start+DSKCM_SLOT_SZ*slot);
if (rsz == -1) {
perror("pwrite slot(dsk_slot_set)");
return errno;
}
rsz = pwrite(dskfd, smp, sizeof(struct slotmeta),
dsk_slotmeta_start+SLOTMETA_SZ*slot);
if (rsz == -1) {
perror("pwrite slotmeta(dsk_slot_set)");
return errno;
}
return 0;
}
int
dsk_write(int dskfd, int slot, const char* msg, size_t msg_size)
{
struct slot *sp;
struct slotmeta *smp;
const char *msg_ptr = msg;
int ri;
ri = dsk_slot_get(dskfd, slot, &sp, &smp);
if (ri != 0) return -1;
smp->seq_number = -1;
smp->gen_number = smp->gen_number + 1;
while (msg_size > DSKCM_SLOT_SZ) {
smp->seq_number = smp->seq_number + 1;
smp->msg_size = DSKCM_SLOT_SZ;
smp->msg_cont = 1;
memcpy(sp->msg, msg_ptr, DSKCM_SLOT_SZ);
msg_ptr += DSKCM_SLOT_SZ;
msg_size -= DSKCM_SLOT_SZ;
compute_chksum(sp->msg, DSKCM_SLOT_SZ, smp->chksum);
// print_chksum("smp->chksum 1", smp->chksum);
if (dsk_slot_set(dskfd, slot, sp, smp) == -1) {
free(sp); free(smp);
return -1;
}
/*
* just assume peers recv it in time
* yes, we are not reliable :)
*/
//mysleep(0.5);
mysleep(0.2);
}
smp->seq_number = smp->seq_number + 1;
smp->msg_size = msg_size;
smp->msg_cont = 0;
memcpy(sp->msg, msg_ptr, msg_size);
compute_chksum(sp->msg, smp->msg_size, smp->chksum);
if (dsk_slot_set(dskfd, slot, sp, smp) == -1) {
free(sp); free(smp);
return -1;
}
free(sp); free(smp);
return 0;
}
/*
* Receive a heartbeat broadcast packet from DSKCM interface
*/
char dskcm_pkt[MAXMSG];
void *
dskcm_read(struct hb_media* mp, int * lenp)
{
struct dskcm_private * dpi;
int numbytes;
int arri_slot;
void* buf;
DSKCMASSERT(mp);
dpi = (struct dskcm_private *) mp->pd;
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG
, "dskcm_read : reading from device %s slot %d"
, dpi->dskn, dpi->slot);
}
/* read available */
//read_new_arrival(int dskfd, int slot, int* arri_slot, void** rbuf);
numbytes = read_new_arrival(dpi->dskfd, dpi->slot, &arri_slot, &buf);
if (numbytes == -1) {
PILCallLog(LOG, PIL_CRIT
, "Error receiving from disk %s: %s"
, dpi->dskn, strerror(errno));
return NULL;
}
memcpy(dskcm_pkt, buf, numbytes);
free(buf);
/* Avoid possible buffer overruns */
dskcm_pkt[numbytes] = EOS;
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG, "got %d byte packet from %s slot %d"
, numbytes, dpi->dskn, dpi->slot);
}
if (DEBUGPKTCONT && numbytes > 0) {
PILCallLog(LOG, PIL_DEBUG, "%s", dskcm_pkt);
}
*lenp = numbytes +1;
return dskcm_pkt;
}
static int
dskcm_write(struct hb_media* mp, void *pkt, int len)
{
struct dskcm_private * dpi;
int rc;
DSKCMASSERT(mp);
dpi = (struct dskcm_private *) mp->pd;
// int
//dsk_write(int dskfd, int slot, const char* msg, size_t msg_size)
rc = dsk_write(dpi->dskfd, dpi->slot, (const char*)pkt, len);
if (rc == -1) {
struct ha_msg* m;
int err = errno;
PILCallLog(LOG, PIL_CRIT, "Unable to send dskcm [%d] packet(len=%d): %s",
rc,len, strerror(err));
m = wirefmt2msg(pkt, len,MSG_NEEDAUTH);
if (m){
cl_log_message(LOG_ERR, m);
ha_msg_del(m);
}
errno = err;
return(HA_FAIL);
}
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG
, "dskcm_write : writing %d bytes to %s (slot %d)"
, rc, dpi->dskn, dpi->slot);
}
if (DEBUGPKTCONT) {
PILCallLog(LOG, PIL_DEBUG, "dskcm pkt out: [%s]", (char*)pkt);
}
mysleep(0.3);
return(HA_OK);
}
static int
dskcm_parse(const char* line)
{
const char* bp = line;
char dev[MAXLINE];
char token[MAXLINE];
int slot;
int toklen;
struct hb_media *mp;
bp += strspn(bp, WHITESPACE);
toklen = strcspn(bp, WHITESPACE);
strncpy(dev, bp, toklen);
bp += toklen;
dev[toklen] = EOS;
if (*dev == EOS) {
PILCallLog(LOG, PIL_CRIT, "dskcm device is not set");
return HA_FAIL;
}
if (is_valid_dev(dev) == -1) {
PILCallLog(LOG, PIL_CRIT, "dskcm device [%s] is invalid or not set up properly", dev);
return HA_FAIL;
}
bp += strspn(bp, WHITESPACE);
toklen = strcspn(bp, WHITESPACE);
strncpy(token, bp, toklen);
bp += toklen;
token[toklen] = EOS;
if (*token == EOS) {
PILCallLog(LOG, PIL_CRIT, "dskcm [%s] missing slot", dev);
return HA_FAIL;
}
if (get_slot(token, &slot) < 0) {
PILCallLog(LOG, PIL_CRIT, "dskcm [%s] invalid slot [%d]", dev, slot);
return HA_FAIL;
}
if ((mp = dskcm_new(dev, slot)) == NULL) {
return HA_FAIL;
}
OurImports->RegisterNewMedium(mp);
return HA_OK;
}
static struct dskcm_private*
new_dskcm_private(const char* dev, int slot)
{
struct dskcm_private *dpi;
dpi = MALLOC(sizeof(struct dskcm_private));
if (dpi == NULL)
return NULL;
dpi->dskn = (char*)STRDUP(dev);
if (dpi->dskn == NULL) {
FREE(dpi);
return NULL;
}
dpi->slot = slot;
dpi->dskfd = -1;
return dpi;
}
static struct hb_media *
dskcm_new(const char * dev, int slot)
{
struct dskcm_private* dpi;
struct hb_media * ret;
dpi = new_dskcm_private(dev, slot);
if (dpi == NULL) {
PILCallLog(LOG, PIL_CRIT, "Create dskcm_private failed");
return(NULL);
}
ret = (struct hb_media*) MALLOC(sizeof(struct hb_media));
if (ret != NULL) {
char * name;
memset(ret, 0, sizeof(*ret));
ret->pd = (void*)dpi;
name = STRDUP(dev);
if (name != NULL) {
ret->name = name;
} else {
FREE(ret);
ret = NULL;
}
}
if (ret != NULL) {
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG,
"dskcm_new: returning ret (%s)",
ret->name);
}
}else{
FREE(dpi->dskn);
FREE(dpi);
if (DEBUGPKT) {
PILCallLog(LOG, PIL_DEBUG, "dskcm_new: ret was NULL");
}
}
return(ret);
}
static void SHA1_Init(SHA_CTX *ctx) {
int i;
ctx->lenW = 0;
ctx->sizeHi = ctx->sizeLo = 0;
/* Initialize H with the magic constants (see FIPS180 for constants)
*/
ctx->H[0] = 0x67452301;
ctx->H[1] = 0xefcdab89;
ctx->H[2] = 0x98badcfe;
ctx->H[3] = 0x10325476;
ctx->H[4] = 0xc3d2e1f0;
for (i = 0; i < 80; i++)
ctx->W[i] = 0;
}
static void SHA1_Update(SHA_CTX *ctx, const void *_dataIn, int len) {
const unsigned char *dataIn = _dataIn;
int i;
/* Read the data into W and process blocks as they get full
*/
for (i = 0; i < len; i++) {
ctx->W[ctx->lenW / 4] <<= 8;
ctx->W[ctx->lenW / 4] |= (unsigned int)dataIn[i];
if ((++ctx->lenW) % 64 == 0) {
shaHashBlock(ctx);
ctx->lenW = 0;
}
ctx->sizeLo += 8;
ctx->sizeHi += (ctx->sizeLo < 8);
}
}
static void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) {
unsigned char pad0x80 = 0x80;
unsigned char pad0x00 = 0x00;
unsigned char padlen[8];
int i;
/* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
*/
padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
SHA1_Update(ctx, &pad0x80, 1);
while (ctx->lenW != 56)
SHA1_Update(ctx, &pad0x00, 1);
SHA1_Update(ctx, padlen, 8);
/* Output hash
*/
for (i = 0; i < 20; i++) {
hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
ctx->H[i / 4] <<= 8;
}
/*
* Re-initialize the context (also zeroizes contents)
*/
SHA1_Init(ctx);
}
#define SHA_ROT(X,n) (((X) << (n)) | ((X) >> (32-(n))))
static void shaHashBlock(SHA_CTX *ctx) {
int t;
unsigned int A,B,C,D,E,TEMP;
for (t = 16; t <= 79; t++)
ctx->W[t] =
SHA_ROT(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1);
A = ctx->H[0];
B = ctx->H[1];
C = ctx->H[2];
D = ctx->H[3];
E = ctx->H[4];
for (t = 0; t <= 19; t++) {
TEMP = SHA_ROT(A,5) + (((C^D)&B)^D) + E + ctx->W[t] + 0x5a827999;
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
}
for (t = 20; t <= 39; t++) {
TEMP = SHA_ROT(A,5) + (B^C^D) + E + ctx->W[t] + 0x6ed9eba1;
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
}
for (t = 40; t <= 59; t++) {
TEMP = SHA_ROT(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdc;
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
}
for (t = 60; t <= 79; t++) {
TEMP = SHA_ROT(A,5) + (B^C^D) + E + ctx->W[t] + 0xca62c1d6;
E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
}
ctx->H[0] += A;
ctx->H[1] += B;
ctx->H[2] += C;
ctx->H[3] += D;
ctx->H[4] += E;
}
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/