xref: /freebsd/contrib/blocklist/bin/state.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 /*	$NetBSD: state.c,v 1.19 2016/09/26 19:43:43 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2015 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: state.c,v 1.19 2016/09/26 19:43:43 christos Exp $");
37 
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <syslog.h>
45 #include <netinet/in.h>
46 
47 #include "bl.h"
48 #include "internal.h"
49 #include "conf.h"
50 #include "support.h"
51 #include "state.h"
52 
53 static HASHINFO openinfo = {
54 	4096,		/* bsize */
55 	32,		/* ffactor */
56 	256,		/* nelem */
57 	8 * 1024 * 1024,/* cachesize */
58 	NULL,		/* hash() */
59 	0		/* lorder */
60 };
61 
62 int
63 state_close(DB *db)
64 {
65 	if (db == NULL)
66 		return -1;
67 	if ((*db->close)(db) == -1) {
68 		    (*lfun)(LOG_ERR, "%s: can't close db (%m)", __func__);
69 		    return -1;
70 	}
71 	return 0;
72 }
73 
74 DB *
75 state_open(const char *dbname, int flags, mode_t perm)
76 {
77 	DB *db;
78 
79 #ifdef __APPLE__
80 	flags &= O_CREAT|O_EXCL|O_EXLOCK|O_NONBLOCK|O_RDONLY|
81 	     O_RDWR|O_SHLOCK|O_TRUNC;
82 #endif
83 	db = dbopen(dbname, flags, perm, DB_HASH, &openinfo);
84 	if (db == NULL) {
85 		if (errno == ENOENT && (flags & O_CREAT) == 0)
86 			return NULL;
87 		(*lfun)(LOG_ERR, "%s: can't open `%s' (%m)", __func__, dbname);
88 	}
89 	return db;
90 }
91 
92 static int
93 state_sizecheck(const DBT *t)
94 {
95 	if (sizeof(struct conf) == t->size)
96 		return 0;
97 	(*lfun)(LOG_ERR, "Key size mismatch %zu != %zu", sizeof(struct conf),
98 	    t->size);
99 	return -1;
100 }
101 
102 static void
103 dumpkey(const struct conf *k)
104 {
105 	char buf[10240];
106 	blhexdump(buf, sizeof(buf), __func__, k, sizeof(*k));
107 	(*lfun)(LOG_DEBUG, "%s", buf);
108 	(*lfun)(LOG_DEBUG, "%s: %s", __func__,
109 	    conf_print(buf, sizeof(buf), "", "", k));
110 
111 }
112 
113 int
114 state_del(DB *db, const struct conf *c)
115 {
116 	int rv;
117 	DBT k;
118 
119 	if (db == NULL)
120 		return -1;
121 
122 	k.data = __UNCONST(c);
123 	k.size = sizeof(*c);
124 
125 	switch (rv = (*db->del)(db, &k, 0)) {
126 	case 0:
127 	case 1:
128 		if (debug > 1) {
129 			(*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
130 			(*db->sync)(db, 0);
131 		}
132 		return 0;
133 	default:
134 		(*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
135 		return -1;
136 	}
137 }
138 
139 int
140 state_get(DB *db, const struct conf *c, struct dbinfo *dbi)
141 {
142 	int rv;
143 	DBT k, v;
144 
145 	if (db == NULL)
146 		return -1;
147 
148 	k.data = __UNCONST(c);
149 	k.size = sizeof(*c);
150 
151 	switch (rv = (*db->get)(db, &k, &v, 0)) {
152 	case 0:
153 	case 1:
154 		if (rv)
155 			memset(dbi, 0, sizeof(*dbi));
156 		else
157 			memcpy(dbi, v.data, sizeof(*dbi));
158 		if (debug > 1)
159 			(*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
160 		return 0;
161 	default:
162 		(*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
163 		return -1;
164 	}
165 }
166 
167 int
168 state_put(DB *db, const struct conf *c, const struct dbinfo *dbi)
169 {
170 	int rv;
171 	DBT k, v;
172 
173 	if (db == NULL)
174 		return -1;
175 
176 	k.data = __UNCONST(c);
177 	k.size = sizeof(*c);
178 	v.data = __UNCONST(dbi);
179 	v.size = sizeof(*dbi);
180 
181 	switch (rv = (*db->put)(db, &k, &v, 0)) {
182 	case 0:
183 		if (debug > 1) {
184 			(*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
185 			(*db->sync)(db, 0);
186 		}
187 		return 0;
188 	case 1:
189 		errno = EEXIST;
190 		/*FALLTHROUGH*/
191 	default:
192 		(*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
193 		return -1;
194 	}
195 }
196 
197 int
198 state_iterate(DB *db, struct conf *c, struct dbinfo *dbi, unsigned int first)
199 {
200 	int rv;
201 	DBT k, v;
202 
203 	if (db == NULL) {
204 		(*lfun)(LOG_ERR, "%s: called with no database file", __func__);
205 		return -1;
206 	}
207 
208 	first = first ? R_FIRST : R_NEXT;
209 
210 	switch (rv = (*db->seq)(db, &k, &v, first)) {
211 	case 0:
212 		if (state_sizecheck(&k) == -1)
213 			return -1;
214 		memcpy(c, k.data, sizeof(*c));
215 		if (debug > 2)
216 			dumpkey(c);
217 		memcpy(dbi, v.data, sizeof(*dbi));
218 		if (debug > 1)
219 			(*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
220 		return 1;
221 	case 1:
222 		if (debug > 1)
223 			(*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
224 		return 0;
225 	default:
226 		(*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
227 		return -1;
228 	}
229 }
230 
231 int
232 state_sync(DB *db)
233 {
234 	return (*db->sync)(db, 0);
235 }
236