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