|
|
|
/* Copyright (C) 2014 Open Information Security Foundation
|
|
|
|
*
|
|
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
|
|
* the GNU General Public License version 2 as published by the Free
|
|
|
|
* Software Foundation.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* version 2 along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
*
|
|
|
|
* \author Victor Julien <victor@inliniac.net>
|
|
|
|
*
|
|
|
|
* Implements per host bits. Actually, not a bit,
|
|
|
|
* but called that way because of Snort's flowbits.
|
|
|
|
* It's a binary storage.
|
|
|
|
*
|
|
|
|
* \todo move away from a linked list implementation
|
|
|
|
* \todo use different datatypes, such as string, int, etc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "suricata-common.h"
|
|
|
|
#include "threads.h"
|
|
|
|
#include "host-bit.h"
|
|
|
|
#include "host.h"
|
|
|
|
#include "detect.h"
|
|
|
|
#include "util-var.h"
|
|
|
|
#include "util-debug.h"
|
|
|
|
#include "util-unittest.h"
|
|
|
|
#include "host-storage.h"
|
|
|
|
|
|
|
|
static int host_bit_id = -1; /**< Host storage id for bits */
|
|
|
|
|
|
|
|
static void HostBitFreeAll(void *store)
|
|
|
|
{
|
|
|
|
GenericVar *gv = store;
|
|
|
|
GenericVarFree(gv);
|
|
|
|
}
|
|
|
|
|
|
|
|
void HostBitInitCtx(void)
|
|
|
|
{
|
|
|
|
host_bit_id = HostStorageRegister("bit", sizeof(void *), NULL, HostBitFreeAll);
|
|
|
|
if (host_bit_id == -1) {
|
|
|
|
SCLogError(SC_ERR_HOST_INIT, "Can't initiate host storage for bits");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lock before using this */
|
|
|
|
int HostHasHostBits(Host *host)
|
|
|
|
{
|
|
|
|
if (host == NULL)
|
|
|
|
return 0;
|
|
|
|
return HostGetStorageById(host, host_bit_id) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \retval 1 host timed out wrt xbits
|
|
|
|
* \retval 0 host still has active (non-expired) xbits */
|
|
|
|
int HostBitsTimedoutCheck(Host *h, struct timeval *ts)
|
|
|
|
{
|
|
|
|
GenericVar *gv = HostGetStorageById(h, host_bit_id);
|
|
|
|
for ( ; gv != NULL; gv = gv->next) {
|
|
|
|
if (gv->type == DETECT_XBITS) {
|
|
|
|
XBit *xb = (XBit *)gv;
|
|
|
|
if (xb->expire > (uint32_t)ts->tv_sec)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the bit with idx from the host */
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
static XBit *HostBitGet(Host *h, uint32_t idx)
|
|
|
|
{
|
|
|
|
GenericVar *gv = HostGetStorageById(h, host_bit_id);
|
|
|
|
for ( ; gv != NULL; gv = gv->next) {
|
|
|
|
if (gv->type == DETECT_XBITS && gv->idx == idx) {
|
|
|
|
return (XBit *)gv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add a flowbit to the flow */
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
static void HostBitAdd(Host *h, uint32_t idx, uint32_t expire)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb == NULL) {
|
|
|
|
fb = SCMalloc(sizeof(XBit));
|
|
|
|
if (unlikely(fb == NULL))
|
|
|
|
return;
|
|
|
|
|
|
|
|
fb->type = DETECT_XBITS;
|
|
|
|
fb->idx = idx;
|
|
|
|
fb->next = NULL;
|
|
|
|
fb->expire = expire;
|
|
|
|
|
|
|
|
GenericVar *gv = HostGetStorageById(h, host_bit_id);
|
|
|
|
GenericVarAppend(&gv, (GenericVar *)fb);
|
|
|
|
HostSetStorageById(h, host_bit_id, gv);
|
|
|
|
|
|
|
|
// bit already set, lets update it's time
|
|
|
|
} else {
|
|
|
|
fb->expire = expire;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
static void HostBitRemove(Host *h, uint32_t idx)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GenericVar *gv = HostGetStorageById(h, host_bit_id);
|
|
|
|
if (gv) {
|
|
|
|
GenericVarRemove(&gv, (GenericVar *)fb);
|
|
|
|
XBitFree(fb);
|
|
|
|
HostSetStorageById(h, host_bit_id, gv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
void HostBitSet(Host *h, uint32_t idx, uint32_t expire)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb == NULL) {
|
|
|
|
HostBitAdd(h, idx, expire);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
void HostBitUnset(Host *h, uint32_t idx)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb != NULL) {
|
|
|
|
HostBitRemove(h, idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
void HostBitToggle(Host *h, uint32_t idx, uint32_t expire)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb != NULL) {
|
|
|
|
HostBitRemove(h, idx);
|
|
|
|
} else {
|
|
|
|
HostBitAdd(h, idx, expire);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
int HostBitIsset(Host *h, uint32_t idx, uint32_t ts)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb != NULL) {
|
|
|
|
if (fb->expire < ts) {
|
|
|
|
HostBitRemove(h,idx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
var-names: expose outside of detect engine
Until now variable names, such as flowbit names, were local to a detect
engine. This made sense as they were only ever used in that context.
For the purpose of logging these names, this needs a different approach.
The loggers live outside of the detect engine. Also, in the case of
reloads and multi-tenancy, there are even multiple detect engines, so
it would be even more tricky to access them from the outside.
This patch brings a new approach. A any time, there is a single active
hash table mapping the variable names and their id's. For multiple
tenants the table is shared between tenants.
The table is set up in a 'staging' area, where locking makes sure that
multiple loading threads don't mess things up. Then when the preparing
of a detection engine is ready, but before the detect threads are made
aware of the new detect engine, the active varname hash is swapped with
the staging instance.
For this to work, all the mappings from the 'current' or active mapping
are added to the staging table.
After the threads have reloaded and the new detection engine is active,
the old table can be freed.
For multi tenancy things are similar. The staging area is used for
setting up until the new detection engines / tenants are applied to
the system.
This patch also changes the variable 'id'/'idx' field to uint32_t. Due
to data structure padding and alignment, this should have no practical
drawback while allowing for a lot more vars.
9 years ago
|
|
|
int HostBitIsnotset(Host *h, uint32_t idx, uint32_t ts)
|
|
|
|
{
|
|
|
|
XBit *fb = HostBitGet(h, idx);
|
|
|
|
if (fb == NULL) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fb->expire < ts) {
|
|
|
|
HostBitRemove(h,idx);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int HostBitList(Host *h, XBit **iter)
|
|
|
|
{
|
|
|
|
GenericVar *gv = (GenericVar *)*iter;
|
|
|
|
if (gv == NULL) {
|
|
|
|
gv = HostGetStorageById(h, host_bit_id);
|
|
|
|
} else {
|
|
|
|
gv = gv->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; gv != NULL; gv = gv->next) {
|
|
|
|
if (gv->type == DETECT_XBITS) {
|
|
|
|
*iter = (XBit *)gv;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*iter = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TESTS */
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
static int HostBitTest01 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 0);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,0);
|
|
|
|
if (fb != NULL)
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest02 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,0);
|
|
|
|
if (fb == NULL)
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest03 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 30);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,0);
|
|
|
|
if (fb == NULL) {
|
|
|
|
printf("fb == NULL although it was just added: ");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
HostBitRemove(h, 0);
|
|
|
|
|
|
|
|
fb = HostBitGet(h,0);
|
|
|
|
if (fb != NULL) {
|
|
|
|
printf("fb != NULL although it was just removed: ");
|
|
|
|
goto end;
|
|
|
|
} else {
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest04 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 30);
|
|
|
|
HostBitAdd(h, 1, 30);
|
|
|
|
HostBitAdd(h, 2, 30);
|
|
|
|
HostBitAdd(h, 3, 30);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,0);
|
|
|
|
if (fb != NULL)
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest05 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 30);
|
|
|
|
HostBitAdd(h, 1, 30);
|
|
|
|
HostBitAdd(h, 2, 30);
|
|
|
|
HostBitAdd(h, 3, 30);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,1);
|
|
|
|
if (fb != NULL)
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest06 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 90);
|
|
|
|
HostBitAdd(h, 1, 90);
|
|
|
|
HostBitAdd(h, 2, 90);
|
|
|
|
HostBitAdd(h, 3, 90);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,2);
|
|
|
|
if (fb != NULL)
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest07 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 90);
|
|
|
|
HostBitAdd(h, 1, 90);
|
|
|
|
HostBitAdd(h, 2, 90);
|
|
|
|
HostBitAdd(h, 3, 90);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,3);
|
|
|
|
if (fb != NULL)
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest08 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 90);
|
|
|
|
HostBitAdd(h, 1, 90);
|
|
|
|
HostBitAdd(h, 2, 90);
|
|
|
|
HostBitAdd(h, 3, 90);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,0);
|
|
|
|
if (fb == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitRemove(h,0);
|
|
|
|
|
|
|
|
fb = HostBitGet(h,0);
|
|
|
|
if (fb != NULL) {
|
|
|
|
printf("fb != NULL even though it was removed: ");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest09 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 90);
|
|
|
|
HostBitAdd(h, 1, 90);
|
|
|
|
HostBitAdd(h, 2, 90);
|
|
|
|
HostBitAdd(h, 3, 90);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,1);
|
|
|
|
if (fb == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitRemove(h,1);
|
|
|
|
|
|
|
|
fb = HostBitGet(h,1);
|
|
|
|
if (fb != NULL) {
|
|
|
|
printf("fb != NULL even though it was removed: ");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest10 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 90);
|
|
|
|
HostBitAdd(h, 1, 90);
|
|
|
|
HostBitAdd(h, 2, 90);
|
|
|
|
HostBitAdd(h, 3, 90);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,2);
|
|
|
|
if (fb == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitRemove(h,2);
|
|
|
|
|
|
|
|
fb = HostBitGet(h,2);
|
|
|
|
if (fb != NULL) {
|
|
|
|
printf("fb != NULL even though it was removed: ");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int HostBitTest11 (void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
HostInitConfig(TRUE);
|
|
|
|
Host *h = HostAlloc();
|
|
|
|
if (h == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitAdd(h, 0, 90);
|
|
|
|
HostBitAdd(h, 1, 90);
|
|
|
|
HostBitAdd(h, 2, 90);
|
|
|
|
HostBitAdd(h, 3, 90);
|
|
|
|
|
|
|
|
XBit *fb = HostBitGet(h,3);
|
|
|
|
if (fb == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
HostBitRemove(h,3);
|
|
|
|
|
|
|
|
fb = HostBitGet(h,3);
|
|
|
|
if (fb != NULL) {
|
|
|
|
printf("fb != NULL even though it was removed: ");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
HostFree(h);
|
|
|
|
end:
|
|
|
|
HostCleanup();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
|
|
|
|
void HostBitRegisterTests(void)
|
|
|
|
{
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
UtRegisterTest("HostBitTest01", HostBitTest01);
|
|
|
|
UtRegisterTest("HostBitTest02", HostBitTest02);
|
|
|
|
UtRegisterTest("HostBitTest03", HostBitTest03);
|
|
|
|
UtRegisterTest("HostBitTest04", HostBitTest04);
|
|
|
|
UtRegisterTest("HostBitTest05", HostBitTest05);
|
|
|
|
UtRegisterTest("HostBitTest06", HostBitTest06);
|
|
|
|
UtRegisterTest("HostBitTest07", HostBitTest07);
|
|
|
|
UtRegisterTest("HostBitTest08", HostBitTest08);
|
|
|
|
UtRegisterTest("HostBitTest09", HostBitTest09);
|
|
|
|
UtRegisterTest("HostBitTest10", HostBitTest10);
|
|
|
|
UtRegisterTest("HostBitTest11", HostBitTest11);
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
}
|