xref: /openbsd-src/usr.sbin/dhcpd/hash.c (revision bb9a412af902140214a3adbe1c6394f0c9a93d33)
1*bb9a412aSkrw /*	$OpenBSD: hash.c,v 1.9 2020/11/10 16:42:17 krw Exp $	*/
2e853bc5dShenning 
33c41e82cShenning /* Routines for manipulating hash tables... */
4e853bc5dShenning 
5e853bc5dShenning /*
6e853bc5dShenning  * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
7e853bc5dShenning  * All rights reserved.
8e853bc5dShenning  *
9e853bc5dShenning  * Redistribution and use in source and binary forms, with or without
10e853bc5dShenning  * modification, are permitted provided that the following conditions
11e853bc5dShenning  * are met:
12e853bc5dShenning  *
13e853bc5dShenning  * 1. Redistributions of source code must retain the above copyright
14e853bc5dShenning  *    notice, this list of conditions and the following disclaimer.
15e853bc5dShenning  * 2. Redistributions in binary form must reproduce the above copyright
16e853bc5dShenning  *    notice, this list of conditions and the following disclaimer in the
17e853bc5dShenning  *    documentation and/or other materials provided with the distribution.
18e853bc5dShenning  * 3. Neither the name of The Internet Software Consortium nor the names
19e853bc5dShenning  *    of its contributors may be used to endorse or promote products derived
20e853bc5dShenning  *    from this software without specific prior written permission.
21e853bc5dShenning  *
22e853bc5dShenning  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23e853bc5dShenning  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24e853bc5dShenning  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25e853bc5dShenning  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26e853bc5dShenning  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27e853bc5dShenning  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28e853bc5dShenning  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29e853bc5dShenning  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30e853bc5dShenning  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31e853bc5dShenning  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32e853bc5dShenning  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33e853bc5dShenning  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34e853bc5dShenning  * SUCH DAMAGE.
35e853bc5dShenning  *
36e853bc5dShenning  * This software has been written for the Internet Software Consortium
37e853bc5dShenning  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38e853bc5dShenning  * Enterprises.  To learn more about the Internet Software Consortium,
39e853bc5dShenning  * see ``http://www.vix.com/isc''.  To learn more about Vixie
40e853bc5dShenning  * Enterprises, see ``http://www.vix.com''.
41e853bc5dShenning  */
42e853bc5dShenning 
43837cddffSkrw #include <sys/types.h>
44837cddffSkrw #include <sys/socket.h>
45837cddffSkrw 
46837cddffSkrw #include <net/if.h>
47837cddffSkrw 
48837cddffSkrw #include <netinet/in.h>
49837cddffSkrw 
50837cddffSkrw #include <stdio.h>
51837cddffSkrw #include <stdlib.h>
52837cddffSkrw #include <string.h>
53837cddffSkrw 
54837cddffSkrw #include "dhcp.h"
55837cddffSkrw #include "tree.h"
56e853bc5dShenning #include "dhcpd.h"
57c525a185Skrw #include "log.h"
58e853bc5dShenning 
593c41e82cShenning static int do_hash(unsigned char *, int, int);
60e853bc5dShenning 
613c41e82cShenning struct hash_table *
new_hash(void)623c41e82cShenning new_hash(void)
63e853bc5dShenning {
64750b584aSkrw 	struct hash_table *rv;
65750b584aSkrw 
66750b584aSkrw 	rv = calloc(1, sizeof(struct hash_table));
67e853bc5dShenning 	if (!rv)
68c525a185Skrw 		log_warnx("No memory for new hash.");
69750b584aSkrw 	else
70750b584aSkrw 		rv->hash_count = DEFAULT_HASH_SIZE;
71750b584aSkrw 
723c41e82cShenning 	return (rv);
73e853bc5dShenning }
74e853bc5dShenning 
753c41e82cShenning static int
do_hash(unsigned char * name,int len,int size)763c41e82cShenning do_hash(unsigned char *name, int len, int size)
77e853bc5dShenning {
783c41e82cShenning 	int accum = 0;
793c41e82cShenning 	unsigned char *s = name;
80e853bc5dShenning 	int i = len;
813c41e82cShenning 
82e853bc5dShenning 	while (i--) {
83e853bc5dShenning 		/* Add the character in... */
84e853bc5dShenning 		accum += *s++;
85e853bc5dShenning 		/* Add carry back in... */
863c41e82cShenning 		while (accum > 255)
87e853bc5dShenning 			accum = (accum & 255) + (accum >> 8);
88e853bc5dShenning 	}
893c41e82cShenning 	return (accum % size);
90e853bc5dShenning }
91e853bc5dShenning 
92*bb9a412aSkrw void
add_hash(struct hash_table * table,unsigned char * name,int len,unsigned char * pointer)93*bb9a412aSkrw add_hash(struct hash_table *table, unsigned char *name, int len,
943c41e82cShenning     unsigned char *pointer)
95e853bc5dShenning {
96e853bc5dShenning 	int hashno;
97e853bc5dShenning 	struct hash_bucket *bp;
98e853bc5dShenning 
99e853bc5dShenning 	if (!table)
100e853bc5dShenning 		return;
101e853bc5dShenning 	if (!len)
102e853bc5dShenning 		len = strlen((char *)name);
103e853bc5dShenning 
104e853bc5dShenning 	hashno = do_hash(name, len, table->hash_count);
105773bb22eSkrw 	bp = calloc(1, sizeof(struct hash_bucket));
106e853bc5dShenning 	if (!bp) {
107c525a185Skrw 		log_warnx("Can't add %s to hash table.", name);
108e853bc5dShenning 		return;
109e853bc5dShenning 	}
110e853bc5dShenning 	bp->name = name;
111e853bc5dShenning 	bp->value = pointer;
112e853bc5dShenning 	bp->next = table->buckets[hashno];
113e853bc5dShenning 	bp->len = len;
114e853bc5dShenning 	table->buckets[hashno] = bp;
115e853bc5dShenning }
116e853bc5dShenning 
1173c41e82cShenning void
delete_hash_entry(struct hash_table * table,unsigned char * name,int len)1183c41e82cShenning delete_hash_entry(struct hash_table *table, unsigned char *name, int len)
119e853bc5dShenning {
120e853bc5dShenning 	int hashno;
1213c41e82cShenning 	struct hash_bucket *bp, *pbp = NULL;
122e853bc5dShenning 
123e853bc5dShenning 	if (!table)
124e853bc5dShenning 		return;
125e853bc5dShenning 	if (!len)
126e853bc5dShenning 		len = strlen((char *)name);
127e853bc5dShenning 
128e853bc5dShenning 	hashno = do_hash(name, len, table->hash_count);
129e853bc5dShenning 
1303c41e82cShenning 	/*
1313c41e82cShenning 	 * Go through the list looking for an entry that matches; if we
1323c41e82cShenning 	 * find it, delete it.
1333c41e82cShenning 	 */
134e853bc5dShenning 	for (bp = table->buckets[hashno]; bp; bp = bp->next) {
135e853bc5dShenning 		if ((!bp->len &&
136e853bc5dShenning 		    !strcmp((char *)bp->name, (char *)name)) ||
1373c41e82cShenning 		    (bp->len == len && !memcmp(bp->name, name, len))) {
1383c41e82cShenning 			if (pbp)
139e853bc5dShenning 				pbp->next = bp->next;
1403c41e82cShenning 			else
141e853bc5dShenning 				table->buckets[hashno] = bp->next;
14204b89754Skrw 			free(bp);
143e853bc5dShenning 			break;
144e853bc5dShenning 		}
145e853bc5dShenning 		pbp = bp;	/* jwg, 9/6/96 - nice catch! */
146e853bc5dShenning 	}
147e853bc5dShenning }
148e853bc5dShenning 
1493c41e82cShenning unsigned char *
hash_lookup(struct hash_table * table,unsigned char * name,int len)1503c41e82cShenning hash_lookup(struct hash_table *table, unsigned char *name, int len)
151e853bc5dShenning {
152e853bc5dShenning 	int hashno;
153e853bc5dShenning 	struct hash_bucket *bp;
154e853bc5dShenning 
155e853bc5dShenning 	if (!table)
1563c41e82cShenning 		return (NULL);
157e853bc5dShenning 
158e853bc5dShenning 	if (!len)
159e853bc5dShenning 		len = strlen((char *)name);
160e853bc5dShenning 
161e853bc5dShenning 	hashno = do_hash(name, len, table->hash_count);
162e853bc5dShenning 
1633c41e82cShenning 	for (bp = table->buckets[hashno]; bp; bp = bp->next)
164e853bc5dShenning 		if (len == bp->len && !memcmp(bp->name, name, len))
1653c41e82cShenning 			return (bp->value);
1663c41e82cShenning 
1673c41e82cShenning 	return (NULL);
168e853bc5dShenning }
169