xref: /freebsd/sbin/dhclient/hash.c (revision 47c0859616bfefdd59ce6bbd8dd46882cef4527a)
147c08596SBrooks Davis /*	$OpenBSD: hash.c,v 1.9 2004/05/10 15:30:47 deraadt Exp $	*/
247c08596SBrooks Davis 
347c08596SBrooks Davis /* Routines for manipulating hash tables... */
447c08596SBrooks Davis 
547c08596SBrooks Davis /*
647c08596SBrooks Davis  * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
747c08596SBrooks Davis  * All rights reserved.
847c08596SBrooks Davis  *
947c08596SBrooks Davis  * Redistribution and use in source and binary forms, with or without
1047c08596SBrooks Davis  * modification, are permitted provided that the following conditions
1147c08596SBrooks Davis  * are met:
1247c08596SBrooks Davis  *
1347c08596SBrooks Davis  * 1. Redistributions of source code must retain the above copyright
1447c08596SBrooks Davis  *    notice, this list of conditions and the following disclaimer.
1547c08596SBrooks Davis  * 2. Redistributions in binary form must reproduce the above copyright
1647c08596SBrooks Davis  *    notice, this list of conditions and the following disclaimer in the
1747c08596SBrooks Davis  *    documentation and/or other materials provided with the distribution.
1847c08596SBrooks Davis  * 3. Neither the name of The Internet Software Consortium nor the names
1947c08596SBrooks Davis  *    of its contributors may be used to endorse or promote products derived
2047c08596SBrooks Davis  *    from this software without specific prior written permission.
2147c08596SBrooks Davis  *
2247c08596SBrooks Davis  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
2347c08596SBrooks Davis  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2447c08596SBrooks Davis  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2547c08596SBrooks Davis  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2647c08596SBrooks Davis  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
2747c08596SBrooks Davis  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2847c08596SBrooks Davis  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2947c08596SBrooks Davis  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
3047c08596SBrooks Davis  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3147c08596SBrooks Davis  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3247c08596SBrooks Davis  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3347c08596SBrooks Davis  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3447c08596SBrooks Davis  * SUCH DAMAGE.
3547c08596SBrooks Davis  *
3647c08596SBrooks Davis  * This software has been written for the Internet Software Consortium
3747c08596SBrooks Davis  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
3847c08596SBrooks Davis  * Enterprises.  To learn more about the Internet Software Consortium,
3947c08596SBrooks Davis  * see ``http://www.vix.com/isc''.  To learn more about Vixie
4047c08596SBrooks Davis  * Enterprises, see ``http://www.vix.com''.
4147c08596SBrooks Davis  */
4247c08596SBrooks Davis 
4347c08596SBrooks Davis #include "dhcpd.h"
4447c08596SBrooks Davis 
4547c08596SBrooks Davis static int do_hash(unsigned char *, int, int);
4647c08596SBrooks Davis 
4747c08596SBrooks Davis struct hash_table *
4847c08596SBrooks Davis new_hash(void)
4947c08596SBrooks Davis {
5047c08596SBrooks Davis 	struct hash_table *rv = new_hash_table(DEFAULT_HASH_SIZE);
5147c08596SBrooks Davis 
5247c08596SBrooks Davis 	if (!rv)
5347c08596SBrooks Davis 		return (rv);
5447c08596SBrooks Davis 	memset(&rv->buckets[0], 0,
5547c08596SBrooks Davis 	    DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *));
5647c08596SBrooks Davis 	return (rv);
5747c08596SBrooks Davis }
5847c08596SBrooks Davis 
5947c08596SBrooks Davis static int
6047c08596SBrooks Davis do_hash(unsigned char *name, int len, int size)
6147c08596SBrooks Davis {
6247c08596SBrooks Davis 	unsigned char *s = name;
6347c08596SBrooks Davis 	int accum = 0, i = len;
6447c08596SBrooks Davis 
6547c08596SBrooks Davis 	while (i--) {
6647c08596SBrooks Davis 		/* Add the character in... */
6747c08596SBrooks Davis 		accum += *s++;
6847c08596SBrooks Davis 		/* Add carry back in... */
6947c08596SBrooks Davis 		while (accum > 255)
7047c08596SBrooks Davis 			accum = (accum & 255) + (accum >> 8);
7147c08596SBrooks Davis 	}
7247c08596SBrooks Davis 	return (accum % size);
7347c08596SBrooks Davis }
7447c08596SBrooks Davis 
7547c08596SBrooks Davis void add_hash(struct hash_table *table, unsigned char *name, int len,
7647c08596SBrooks Davis     unsigned char *pointer)
7747c08596SBrooks Davis {
7847c08596SBrooks Davis 	struct hash_bucket *bp;
7947c08596SBrooks Davis 	int hashno;
8047c08596SBrooks Davis 
8147c08596SBrooks Davis 	if (!table)
8247c08596SBrooks Davis 		return;
8347c08596SBrooks Davis 	if (!len)
8447c08596SBrooks Davis 		len = strlen((char *)name);
8547c08596SBrooks Davis 
8647c08596SBrooks Davis 	hashno = do_hash(name, len, table->hash_count);
8747c08596SBrooks Davis 	bp = new_hash_bucket();
8847c08596SBrooks Davis 
8947c08596SBrooks Davis 	if (!bp) {
9047c08596SBrooks Davis 		warning("Can't add %s to hash table.", name);
9147c08596SBrooks Davis 		return;
9247c08596SBrooks Davis 	}
9347c08596SBrooks Davis 	bp->name = name;
9447c08596SBrooks Davis 	bp->value = pointer;
9547c08596SBrooks Davis 	bp->next = table->buckets[hashno];
9647c08596SBrooks Davis 	bp->len = len;
9747c08596SBrooks Davis 	table->buckets[hashno] = bp;
9847c08596SBrooks Davis }
9947c08596SBrooks Davis 
10047c08596SBrooks Davis unsigned char *
10147c08596SBrooks Davis hash_lookup(struct hash_table *table, unsigned char *name, int len)
10247c08596SBrooks Davis {
10347c08596SBrooks Davis 	struct hash_bucket *bp;
10447c08596SBrooks Davis 	int hashno;
10547c08596SBrooks Davis 
10647c08596SBrooks Davis 	if (!table)
10747c08596SBrooks Davis 		return (NULL);
10847c08596SBrooks Davis 
10947c08596SBrooks Davis 	if (!len)
11047c08596SBrooks Davis 		len = strlen((char *)name);
11147c08596SBrooks Davis 
11247c08596SBrooks Davis 	hashno = do_hash(name, len, table->hash_count);
11347c08596SBrooks Davis 
11447c08596SBrooks Davis 	for (bp = table->buckets[hashno]; bp; bp = bp->next)
11547c08596SBrooks Davis 		if (len == bp->len && !memcmp(bp->name, name, len))
11647c08596SBrooks Davis 			return (bp->value);
11747c08596SBrooks Davis 
11847c08596SBrooks Davis 	return (NULL);
11947c08596SBrooks Davis }
120