/*
* $Id: indicies.c,v 1.4 2002/10/17 20:02:30 ljb Exp $
* originally Id: indicies.c,v 1.38 1998/08/07 19:07:46 labovit Exp
*/
/* routines for handling indicies in hashes */
#include <stdio.h>
#include <string.h>
#include "mrt.h"
#include "trace.h"
#include <time.h>
#include <signal.h>
#include "config_file.h"
#include <fcntl.h>
#include <ctype.h>
#include "irrd.h"
extern trace_t *default_trace;
static int irr_hash_store (irr_database_t *database, char *key, char *value);
/* irr_database_store
* 4 count | [2 type | 2 primary/secondary | 2 keylen | 4 offset | 4 len] | ...
*
*/
int irr_database_store (irr_database_t *database, char *key, u_short p_or_s,
enum IRR_OBJECTS type, u_long offset, u_long len) {
hash_item_t *hash_item;
char *buffer, *cp;
u_short _keylen, _type = (u_short) type;
u_int count, _size_old, _size_new;
int ret_code = 1;
_keylen = strlen (key);
convert_toupper(key);
hash_item = HASH_Lookup (database->hash, key);
/* JW want to dissallow duplicate primary key additions of same type */
/* create a new hash entry */
if (hash_item == NULL) {
buffer = malloc (18);
count = 0;
cp = buffer + 4;
_size_new = 18;
}
/* just append the new data to the end of the hash entry */
else {
cp = hash_item->value;
UTIL_GET_NETLONG (count, cp);
if ((count < 0) || (count > 1000)) {
trace (ERROR, default_trace,
"** WARN ** Suspiciously high count value (%d) for %s\n",
count, key);
return -1;
}
cp = hash_item->value; /* reset ptr to keep things simple */
_size_old = 4 + (count * 14);
_size_new = _size_old + 14;
buffer = malloc (_size_new);
memcpy (buffer, cp, _size_old);
cp = buffer + _size_old;
} /* end append data */
UTIL_PUT_NETSHORT (_type, cp); /* type */
UTIL_PUT_NETSHORT (p_or_s, cp); /* primary/secondary */
UTIL_PUT_NETSHORT (_keylen, cp); /* length of key */
UTIL_PUT_NETLONG (offset, cp);
UTIL_PUT_NETLONG (len, cp);
cp = buffer;
count++;
UTIL_PUT_NETLONG (count, cp); /* count */
if (hash_item != NULL) HASH_Remove (database->hash, hash_item);
irr_hash_store (database, key, buffer);
return ret_code;
}
/* irr_hash_store
* store indice in memory
*/
static int irr_hash_store (irr_database_t *database, char *key, char *value) {
hash_item_t *hash_item;
hash_item = New (hash_item_t);
hash_item->key = strdup (key);
hash_item->value = value;
HASH_Insert (database->hash, hash_item);
return (1);
}
int irr_hash_destroy (hash_item_t *hash_item) {
if (hash_item == NULL)
return (1);
if (hash_item->key)
Delete (hash_item->key);
if (hash_item->value)
Delete (hash_item->value);
Delete (hash_item);
return (1);
}
/* irr_database_find_matches
* find matches and extract info from hash table entry
* 4 count | [2 type | 2 primary/secondary | 2 keylen | 4 offset | 4 len] | ...
*/
int irr_database_find_matches (irr_connection_t *irr, char *key,
int p_or_s,
int match_behavior,
enum IRR_OBJECTS type,
u_long *ret_offset, u_long *ret_len) {
irr_database_t *database;
hash_item_t *hash_item = NULL;
u_long offset, len;
u_short _type, _p_or_s, _keylen;
int count, exit_on_match = 0;
char *cp;
convert_toupper(key);
if (match_behavior & RAWHOISD_MODE)
exit_on_match = 1;
LL_Iterate (irr->ll_database, database) {
hash_item = HASH_Lookup (database->hash, key);
if (hash_item == NULL)
continue;
cp = hash_item->value;
UTIL_GET_NETLONG (count, cp);
while (count--) {
_type = _p_or_s = _keylen = 0;
UTIL_GET_NETSHORT (_type, cp);
UTIL_GET_NETSHORT (_p_or_s, cp);
UTIL_GET_NETSHORT (_keylen, cp);
UTIL_GET_NETLONG (offset, cp);
UTIL_GET_NETLONG (len, cp);
/* exact match on keys, so maint-as195 != maintas1955 */
if (strlen (key) != _keylen)
continue;
/*
* if (p_or_s != PRIMARY)
* if (_p_or_s != p_or_s)
* continue;
*
*/
/* check type */
if ((match_behavior & TYPE_MODE) && (type != _type))
continue;
/* if ret_offset is not null, we're loading an object, so fill it in */
if (ret_offset != NULL) {
*ret_offset = offset;
*ret_len = len;
break;
}
irr_build_answer (irr, database->db_fp, _type, offset, len, NULL, database->db_syntax);
/* RAWHOISD_MODE means exit after first the match */
if (exit_on_match)
break;
}
if (exit_on_match)
break;
}
return (1);
}
/* given an object key, find it's offset and length. return 1 if found and
* -1 otherwise.
*/
int find_object_offset_len (irr_database_t *db, char *key,
enum IRR_OBJECTS type,
u_long *offset, u_long *len) {
irr_connection_t irr;
int found = -1;
*len = 0;
irr.ll_database = LL_Create (0);
LL_Add (irr.ll_database, db);
irr_database_find_matches (&irr, key, PRIMARY, RAWHOISD_MODE|TYPE_MODE, type,
offset, len);
LL_Destroy (irr.ll_database);
if (*len > 0)
found = 1;
return (found);
}
/* irr_database_store
* 4 count | [2 type | 2 primary/secondary | 2 keylen | 4 offset | 4 len] | ...
*
*/
int irr_database_remove (irr_database_t *database, char *key, u_short p_or_s,
enum IRR_OBJECTS type, u_long offset, u_long len) {
hash_item_t *hash_item;
char *cp;
char *buffer_new = NULL, *cp_new;
u_short _type = (u_short) type;
u_long _offset, _len, _p_or_s, _keylen;
int count, size = 0, ret_code = 1;
_offset = _len = _p_or_s = 0;
convert_toupper (key);
hash_item = HASH_Lookup (database->hash, key);
if (hash_item == NULL)
return -1;
cp = hash_item->value;
UTIL_GET_NETLONG (count, cp);
if (--count > 0) {
/*
size = (4 + (count * 12) + 1);
*/
size = 4 + (count * 14);
cp_new = buffer_new = malloc (size);
UTIL_PUT_NETLONG (count -1, cp_new);
while (count--) {
UTIL_GET_NETSHORT (_type, cp); /* type */
UTIL_GET_NETSHORT (_p_or_s, cp); /* primary/secondary */
UTIL_GET_NETSHORT (_keylen, cp); /* primary/secondary */
UTIL_GET_NETLONG (_offset, cp);
UTIL_GET_NETLONG (_len, cp);
if (offset == _offset) continue; /* skip this delete entry */
UTIL_PUT_NETSHORT (_type, cp_new); /* type */
UTIL_PUT_NETSHORT (_p_or_s, cp_new); /* primary/secondary */
UTIL_PUT_NETSHORT (_keylen, cp_new);
UTIL_PUT_NETLONG (_offset, cp_new);
UTIL_PUT_NETLONG (_len, cp_new);
}
}
/* JW: I think this section can be optimized later,
* for case count > 0 just Delete(hash_item->value) and
* hash_item->value = buffer_new;
*/
HASH_Remove (database->hash, hash_item);
if (count > 0)
irr_hash_store (database, key, buffer_new);
return ret_code;
}
syntax highlighted by Code2HTML, v. 0.9.1