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
state_close(DB * db)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 *
state_open(const char * dbname,int flags,mode_t perm)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
state_sizecheck(const DBT * t)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
dumpkey(const struct conf * k)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
state_del(DB * db,const struct conf * c)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
state_get(DB * db,const struct conf * c,struct dbinfo * dbi)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
state_put(DB * db,const struct conf * c,const struct dbinfo * dbi)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
state_iterate(DB * db,struct conf * c,struct dbinfo * dbi,unsigned int first)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
state_sync(DB * db)232 state_sync(DB *db)
233 {
234 return (*db->sync)(db, 0);
235 }
236