1 /* $NetBSD: state.c,v 1.17 2015/06/02 14:02:10 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.17 2015/06/02 14:02:10 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 hexdump(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 return -1;
205
206 first = first ? R_FIRST : R_NEXT;
207
208 switch (rv = (*db->seq)(db, &k, &v, first)) {
209 case 0:
210 if (state_sizecheck(&k) == -1)
211 return -1;
212 memcpy(c, k.data, sizeof(*c));
213 if (debug > 2)
214 dumpkey(c);
215 memcpy(dbi, v.data, sizeof(*dbi));
216 if (debug > 1)
217 (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
218 return 1;
219 case 1:
220 if (debug > 1)
221 (*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
222 return 0;
223 default:
224 (*lfun)(LOG_ERR, "%s: failed (%m)", __func__);
225 return -1;
226 }
227 }
228
229 int
state_sync(DB * db)230 state_sync(DB *db)
231 {
232 return (*db->sync)(db, 0);
233 }
234