xref: /netbsd-src/external/bsd/ntp/dist/sntp/kod_management.c (revision c505c4429840c353a86d4eb53b5e2bfc0092264e)
1 /*	$NetBSD: kod_management.c,v 1.1.1.1 2009/12/13 16:57:10 kardel Exp $	*/
2 
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 
7 #include "kod_management.h"
8 #include "log.h"
9 #include "sntp-opts.h"
10 #include "ntp_stdlib.h"
11 #define DEBUG
12 
13 int kod_init = 0, kod_db_cnt = 0;
14 const char *kod_db_file;
15 struct kod_entry **kod_db;	/* array of pointers to kod_entry */
16 
17 
18 /*
19  * Search for a KOD entry
20  */
21 int
22 search_entry (
23 		char *hostname,
24 		struct kod_entry **dst
25 	     )
26 {
27 	register int a, b, resc = 0;
28 
29 	for (a = 0; a < kod_db_cnt; a++)
30 		if (!strcmp(kod_db[a]->hostname, hostname))
31 			resc++;
32 
33 	if (!resc) {
34 		*dst = NULL;
35 		return 0;
36 	}
37 
38 	*dst = emalloc(resc * sizeof(**dst));
39 
40 	b = 0;
41 	for (a = 0; a < kod_db_cnt; a++)
42 		if (!strcmp(kod_db[a]->hostname, hostname)) {
43 			(*dst)[b] = *kod_db[a];
44 			b++;
45 		}
46 
47 	return resc;
48 }
49 
50 
51 void
52 add_entry(
53 	char *hostname,
54 	char *type	/* 4 bytes not \0 terminated */
55 	)
56 {
57 	int n;
58 	struct kod_entry *pke;
59 
60 	pke = emalloc(sizeof(*pke));
61 	pke->timestamp = time(NULL);
62 	memcpy(pke->type, type, 4);
63 	pke->type[sizeof(pke->type) - 1] = '\0';
64 	strncpy(pke->hostname, hostname,
65 		sizeof(pke->hostname));
66 	pke->hostname[sizeof(pke->hostname) - 1] = '\0';
67 
68 	/*
69 	 * insert in address ("hostname") order to find duplicates
70 	 */
71 	for (n = 0; n < kod_db_cnt; n++)
72 		if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0)
73 			break;
74 
75 	if (n < kod_db_cnt &&
76 	    0 == strcmp(kod_db[n]->hostname, pke->hostname)) {
77 		kod_db[n]->timestamp = pke->timestamp;
78 		return;
79 	}
80 
81 	kod_db_cnt++;
82 	kod_db = erealloc(kod_db, kod_db_cnt * sizeof(kod_db[0]));
83 	if (n != kod_db_cnt - 1)
84 		memmove(&kod_db[n + 1], &kod_db[n],
85 			sizeof(kod_db[0]) * ((kod_db_cnt - 1) - n));
86 	kod_db[n] = pke;
87 }
88 
89 
90 void
91 delete_entry(
92 	char *hostname,
93 	char *type
94 	)
95 {
96 	register int a;
97 
98 	for (a = 0; a < kod_db_cnt; a++)
99 		if (!strcmp(kod_db[a]->hostname, hostname)
100 		    && !strcmp(kod_db[a]->type, type))
101 			break;
102 
103 	if (a == kod_db_cnt)
104 		return;
105 
106 	free(kod_db[a]);
107 	kod_db_cnt--;
108 
109 	if (a < kod_db_cnt)
110 		memmove(&kod_db[a], &kod_db[a + 1],
111 			(kod_db_cnt - a) * sizeof(kod_db[0]));
112 }
113 
114 
115 void
116 write_kod_db(void)
117 {
118 	FILE *db_s;
119 	char *pch;
120 	int dirmode;
121 	register int a;
122 
123 	db_s = fopen(kod_db_file, "w");
124 
125 	/*
126 	 * If opening fails, blindly attempt to create each directory
127 	 * in the path first, then retry the open.
128 	 */
129 	if (NULL == db_s && strlen(kod_db_file)) {
130 		dirmode = S_IRUSR | S_IWUSR | S_IXUSR
131 			| S_IRGRP | S_IXGRP
132 			| S_IROTH | S_IXOTH;
133 		pch = strchr(kod_db_file + 1, DIR_SEP);
134 		while (NULL != pch) {
135 			*pch = '\0';
136 			mkdir(kod_db_file, dirmode);
137 			*pch = DIR_SEP;
138 			pch = strchr(pch + 1, DIR_SEP);
139 		}
140 		db_s = fopen(kod_db_file, "w");
141 	}
142 
143 	if (NULL == db_s) {
144 		char msg[80];
145 
146 		snprintf(msg, sizeof(msg),
147 			 "Can't open KOD db file %s for writing!",
148 			 kod_db_file);
149 #ifdef DEBUG
150 		debug_msg(msg);
151 #endif
152 		log_msg(msg, 2);
153 
154 		return;
155 	}
156 
157 	for (a = 0; a < kod_db_cnt; a++) {
158 		fprintf(db_s, "%16.16llx %s %s\n", (unsigned long long)
159 			kod_db[a]->timestamp, kod_db[a]->type,
160 			kod_db[a]->hostname);
161 	}
162 
163 	fflush(db_s);
164 	fclose(db_s);
165 }
166 
167 
168 void
169 kod_init_kod_db(
170 	const char *db_file
171 	)
172 {
173 	/*
174 	 * Max. of 254 characters for hostname, 10 for timestamp, 4 for
175 	 * kisscode, 2 for spaces, 1 for \n, and 1 for \0
176 	 */
177 	char fbuf[254+10+4+2+1+1];
178 	FILE *db_s;
179 	int a, b, sepc, len;
180 	unsigned long long ull;
181 	char *str_ptr;
182 	char error = 0;
183 
184 	atexit(write_kod_db);
185 
186 #ifdef DEBUG
187 	printf("Initializing KOD DB...\n");
188 #endif
189 
190 	kod_db_file = estrdup(db_file);
191 
192 
193 	db_s = fopen(db_file, "r");
194 
195 	if (NULL == db_s) {
196 		char msg[80];
197 
198 		snprintf(msg, sizeof(msg), "kod_init_kod_db(): Cannot open KoD db file %s", db_file);
199 #ifdef DEBUG
200 		debug_msg(msg);
201 		printf("%s\n", msg);
202 #endif
203 		log_msg(msg, 2);
204 
205 		return;
206 	}
207 
208 	if (ENABLED_OPT(NORMALVERBOSE))
209 		printf("Starting to read KoD file %s...\n", db_file);
210 	/* First let's see how many entries there are and check for right syntax */
211 
212 	while (!feof(db_s) && NULL != fgets(fbuf, sizeof(fbuf), db_s)) {
213 
214 		/* ignore blank lines */
215 		if ('\n' == fbuf[0])
216 			continue;
217 
218 		sepc = 0;
219 		len = strlen(fbuf);
220 		for (a = 0; a < len; a++) {
221 			if (' ' == fbuf[a])
222 				sepc++;
223 
224 			if ('\n' == fbuf[a]) {
225 				if (sepc != 2) {
226 					if (strcmp(db_file, "/dev/null")) {
227 						char msg[80];
228 						snprintf(msg, sizeof(msg),
229 							 "Syntax error in KoD db file %s in line %i (missing space)",
230 							 db_file, kod_db_cnt + 1);
231 	#ifdef DEBUG
232 						debug_msg(msg);
233 						printf("%s\n", msg);
234 	#endif
235 						log_msg(msg, 1);
236 					}
237 					fclose(db_s);
238 					return;
239 				}
240 				sepc = 0;
241 				kod_db_cnt++;
242 			}
243 		}
244 	}
245 
246 	if (0 == kod_db_cnt) {
247 #ifdef DEBUG
248 		printf("KoD DB %s empty.\n", db_file);
249 #endif
250 		fclose(db_s);
251 		return;
252 	}
253 
254 #ifdef DEBUG
255 	printf("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt);
256 #endif
257 
258 	rewind(db_s);
259 
260 	kod_db = emalloc(sizeof(kod_db[0]) * kod_db_cnt);
261 
262 	/* Read contents of file */
263 	for (b = 0;
264 	     !feof(db_s) && !ferror(db_s) && b < kod_db_cnt;
265 	     b++) {
266 
267 		str_ptr = fgets(fbuf, sizeof(fbuf), db_s);
268 		if (NULL == str_ptr) {
269 			error = 1;
270 			break;
271 		}
272 
273 		/* ignore blank lines */
274 		if ('\n' == fbuf[0]) {
275 			b--;
276 			continue;
277 		}
278 
279 		kod_db[b] = emalloc(sizeof(*kod_db[b]));
280 
281 		if (3 != sscanf(fbuf, "%llx %4s %254s", &ull,
282 		    kod_db[b]->type, kod_db[b]->hostname)) {
283 
284 			free(kod_db[b]);
285 			kod_db[b] = NULL;
286 			error = 1;
287 			break;
288 		}
289 
290 		kod_db[b]->timestamp = (time_t)ull;
291 	}
292 
293 	if (ferror(db_s) || error) {
294 		char msg[80];
295 
296 		kod_db_cnt = b;
297 		snprintf(msg, sizeof(msg), "An error occured while parsing the KoD db file %s", db_file);
298 #ifdef DEBUG
299 		debug_msg(msg);
300 #endif
301 		log_msg(msg, 2);
302 		fclose(db_s);
303 
304 		return;
305 	}
306 
307 	fclose(db_s);
308 #ifdef DEBUG
309 	for (a = 0; a < kod_db_cnt; a++)
310 		printf("KoD entry %d: %s at %llx type %s\n", a,
311 		       kod_db[a]->hostname,
312 		       (unsigned long long)kod_db[a]->timestamp,
313 		       kod_db[a]->type);
314 #endif
315 }
316