kod_management.c revision 258945
1258945Sroberto#include <config.h>
2258945Sroberto#include <string.h>
3258945Sroberto#include <sys/types.h>
4258945Sroberto#include <sys/stat.h>
5258945Sroberto
6258945Sroberto#include "kod_management.h"
7258945Sroberto#include "log.h"
8258945Sroberto#include "sntp-opts.h"
9258945Sroberto#include "ntp_stdlib.h"
10258945Sroberto//#define DEBUG
11258945Sroberto
12258945Srobertoint kod_init = 0, kod_db_cnt = 0;
13258945Srobertoconst char *kod_db_file;
14258945Srobertostruct kod_entry **kod_db;	/* array of pointers to kod_entry */
15258945Sroberto
16258945Sroberto
17258945Sroberto/*
18258945Sroberto * Search for a KOD entry
19258945Sroberto */
20258945Srobertoint
21258945Srobertosearch_entry (
22258945Sroberto		char *hostname,
23258945Sroberto		struct kod_entry **dst
24258945Sroberto	     )
25258945Sroberto{
26258945Sroberto	register int a, b, resc = 0;
27258945Sroberto
28258945Sroberto	for (a = 0; a < kod_db_cnt; a++)
29258945Sroberto		if (!strcmp(kod_db[a]->hostname, hostname))
30258945Sroberto			resc++;
31258945Sroberto
32258945Sroberto	if (!resc) {
33258945Sroberto		*dst = NULL;
34258945Sroberto		return 0;
35258945Sroberto	}
36258945Sroberto
37258945Sroberto	*dst = emalloc(resc * sizeof(**dst));
38258945Sroberto
39258945Sroberto	b = 0;
40258945Sroberto	for (a = 0; a < kod_db_cnt; a++)
41258945Sroberto		if (!strcmp(kod_db[a]->hostname, hostname)) {
42258945Sroberto			(*dst)[b] = *kod_db[a];
43258945Sroberto			b++;
44258945Sroberto		}
45258945Sroberto
46258945Sroberto	return resc;
47258945Sroberto}
48258945Sroberto
49258945Sroberto
50258945Srobertovoid
51258945Srobertoadd_entry(
52258945Sroberto	char *hostname,
53258945Sroberto	char *type	/* 4 bytes not \0 terminated */
54258945Sroberto	)
55258945Sroberto{
56258945Sroberto	int n;
57258945Sroberto	struct kod_entry *pke;
58258945Sroberto
59258945Sroberto	pke = emalloc(sizeof(*pke));
60258945Sroberto	pke->timestamp = time(NULL);
61258945Sroberto	memcpy(pke->type, type, 4);
62258945Sroberto	pke->type[sizeof(pke->type) - 1] = '\0';
63258945Sroberto	strncpy(pke->hostname, hostname,
64258945Sroberto		sizeof(pke->hostname));
65258945Sroberto	pke->hostname[sizeof(pke->hostname) - 1] = '\0';
66258945Sroberto
67258945Sroberto	/*
68258945Sroberto	 * insert in address ("hostname") order to find duplicates
69258945Sroberto	 */
70258945Sroberto	for (n = 0; n < kod_db_cnt; n++)
71258945Sroberto		if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0)
72258945Sroberto			break;
73258945Sroberto
74258945Sroberto	if (n < kod_db_cnt &&
75258945Sroberto	    0 == strcmp(kod_db[n]->hostname, pke->hostname)) {
76258945Sroberto		kod_db[n]->timestamp = pke->timestamp;
77258945Sroberto		free(pke);
78258945Sroberto		return;
79258945Sroberto	}
80258945Sroberto
81258945Sroberto	kod_db_cnt++;
82258945Sroberto	kod_db = erealloc(kod_db, kod_db_cnt * sizeof(kod_db[0]));
83258945Sroberto	if (n != kod_db_cnt - 1)
84258945Sroberto		memmove(&kod_db[n + 1], &kod_db[n],
85258945Sroberto			sizeof(kod_db[0]) * ((kod_db_cnt - 1) - n));
86258945Sroberto	kod_db[n] = pke;
87258945Sroberto}
88258945Sroberto
89258945Sroberto
90258945Srobertovoid
91258945Srobertodelete_entry(
92258945Sroberto	char *hostname,
93258945Sroberto	char *type
94258945Sroberto	)
95258945Sroberto{
96258945Sroberto	register int a;
97258945Sroberto
98258945Sroberto	for (a = 0; a < kod_db_cnt; a++)
99258945Sroberto		if (!strcmp(kod_db[a]->hostname, hostname)
100258945Sroberto		    && !strcmp(kod_db[a]->type, type))
101258945Sroberto			break;
102258945Sroberto
103258945Sroberto	if (a == kod_db_cnt)
104258945Sroberto		return;
105258945Sroberto
106258945Sroberto	free(kod_db[a]);
107258945Sroberto	kod_db_cnt--;
108258945Sroberto
109258945Sroberto	if (a < kod_db_cnt)
110258945Sroberto		memmove(&kod_db[a], &kod_db[a + 1],
111258945Sroberto			(kod_db_cnt - a) * sizeof(kod_db[0]));
112258945Sroberto}
113258945Sroberto
114258945Sroberto
115258945Srobertovoid
116258945Srobertowrite_kod_db(void)
117258945Sroberto{
118258945Sroberto	FILE *db_s;
119258945Sroberto	char *pch;
120258945Sroberto	int dirmode;
121258945Sroberto	register int a;
122258945Sroberto
123258945Sroberto	db_s = fopen(kod_db_file, "w");
124258945Sroberto
125258945Sroberto	/*
126258945Sroberto	 * If opening fails, blindly attempt to create each directory
127258945Sroberto	 * in the path first, then retry the open.
128258945Sroberto	 */
129258945Sroberto	if (NULL == db_s && strlen(kod_db_file)) {
130258945Sroberto		dirmode = S_IRUSR | S_IWUSR | S_IXUSR
131258945Sroberto			| S_IRGRP | S_IXGRP
132258945Sroberto			| S_IROTH | S_IXOTH;
133258945Sroberto		pch = strchr(kod_db_file + 1, DIR_SEP);
134258945Sroberto		while (NULL != pch) {
135258945Sroberto			*pch = '\0';
136258945Sroberto			mkdir(kod_db_file, dirmode);
137258945Sroberto			*pch = DIR_SEP;
138258945Sroberto			pch = strchr(pch + 1, DIR_SEP);
139258945Sroberto		}
140258945Sroberto		db_s = fopen(kod_db_file, "w");
141258945Sroberto	}
142258945Sroberto
143258945Sroberto	if (NULL == db_s) {
144258945Sroberto		msyslog(LOG_WARNING, "Can't open KOD db file %s for writing!",
145258945Sroberto			kod_db_file);
146258945Sroberto
147258945Sroberto		return;
148258945Sroberto	}
149258945Sroberto
150258945Sroberto	for (a = 0; a < kod_db_cnt; a++) {
151258945Sroberto		fprintf(db_s, "%16.16llx %s %s\n", (unsigned long long)
152258945Sroberto			kod_db[a]->timestamp, kod_db[a]->type,
153258945Sroberto			kod_db[a]->hostname);
154258945Sroberto	}
155258945Sroberto
156258945Sroberto	fflush(db_s);
157258945Sroberto	fclose(db_s);
158258945Sroberto}
159258945Sroberto
160258945Sroberto
161258945Srobertovoid
162258945Srobertokod_init_kod_db(
163258945Sroberto	const char *db_file
164258945Sroberto	)
165258945Sroberto{
166258945Sroberto	/*
167258945Sroberto	 * Max. of 254 characters for hostname, 10 for timestamp, 4 for
168258945Sroberto	 * kisscode, 2 for spaces, 1 for \n, and 1 for \0
169258945Sroberto	 */
170258945Sroberto	char fbuf[254+10+4+2+1+1];
171258945Sroberto	FILE *db_s;
172258945Sroberto	int a, b, sepc, len;
173258945Sroberto	unsigned long long ull;
174258945Sroberto	char *str_ptr;
175258945Sroberto	char error = 0;
176258945Sroberto
177258945Sroberto	atexit(write_kod_db);
178258945Sroberto
179258945Sroberto#ifdef DEBUG
180258945Sroberto	printf("Initializing KOD DB...\n");
181258945Sroberto#endif
182258945Sroberto
183258945Sroberto	kod_db_file = estrdup(db_file);
184258945Sroberto
185258945Sroberto
186258945Sroberto	db_s = fopen(db_file, "r");
187258945Sroberto
188258945Sroberto	if (NULL == db_s) {
189258945Sroberto		msyslog(LOG_WARNING, "kod_init_kod_db(): Cannot open KoD db file %s",
190258945Sroberto			db_file);
191258945Sroberto
192258945Sroberto		return;
193258945Sroberto	}
194258945Sroberto
195258945Sroberto	if (ENABLED_OPT(NORMALVERBOSE))
196258945Sroberto		printf("Starting to read KoD file %s...\n", db_file);
197258945Sroberto	/* First let's see how many entries there are and check for right syntax */
198258945Sroberto
199258945Sroberto	while (!feof(db_s) && NULL != fgets(fbuf, sizeof(fbuf), db_s)) {
200258945Sroberto
201258945Sroberto		/* ignore blank lines */
202258945Sroberto		if ('\n' == fbuf[0])
203258945Sroberto			continue;
204258945Sroberto
205258945Sroberto		sepc = 0;
206258945Sroberto		len = strlen(fbuf);
207258945Sroberto		for (a = 0; a < len; a++) {
208258945Sroberto			if (' ' == fbuf[a])
209258945Sroberto				sepc++;
210258945Sroberto
211258945Sroberto			if ('\n' == fbuf[a]) {
212258945Sroberto				if (sepc != 2) {
213258945Sroberto					if (strcmp(db_file, "/dev/null"))
214258945Sroberto						msyslog(LOG_DEBUG,
215258945Sroberto							"Syntax error in KoD db file %s in line %i (missing space)",
216258945Sroberto							db_file,
217258945Sroberto							kod_db_cnt + 1);
218258945Sroberto					fclose(db_s);
219258945Sroberto					return;
220258945Sroberto				}
221258945Sroberto				sepc = 0;
222258945Sroberto				kod_db_cnt++;
223258945Sroberto			}
224258945Sroberto		}
225258945Sroberto	}
226258945Sroberto
227258945Sroberto	if (0 == kod_db_cnt) {
228258945Sroberto#ifdef DEBUG
229258945Sroberto		printf("KoD DB %s empty.\n", db_file);
230258945Sroberto#endif
231258945Sroberto		fclose(db_s);
232258945Sroberto		return;
233258945Sroberto	}
234258945Sroberto
235258945Sroberto#ifdef DEBUG
236258945Sroberto	printf("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt);
237258945Sroberto#endif
238258945Sroberto
239258945Sroberto	rewind(db_s);
240258945Sroberto
241258945Sroberto	kod_db = emalloc(sizeof(kod_db[0]) * kod_db_cnt);
242258945Sroberto
243258945Sroberto	/* Read contents of file */
244258945Sroberto	for (b = 0;
245258945Sroberto	     !feof(db_s) && !ferror(db_s) && b < kod_db_cnt;
246258945Sroberto	     b++) {
247258945Sroberto
248258945Sroberto		str_ptr = fgets(fbuf, sizeof(fbuf), db_s);
249258945Sroberto		if (NULL == str_ptr) {
250258945Sroberto			error = 1;
251258945Sroberto			break;
252258945Sroberto		}
253258945Sroberto
254258945Sroberto		/* ignore blank lines */
255258945Sroberto		if ('\n' == fbuf[0]) {
256258945Sroberto			b--;
257258945Sroberto			continue;
258258945Sroberto		}
259258945Sroberto
260258945Sroberto		kod_db[b] = emalloc(sizeof(*kod_db[b]));
261258945Sroberto
262258945Sroberto		if (3 != sscanf(fbuf, "%llx %4s %254s", &ull,
263258945Sroberto		    kod_db[b]->type, kod_db[b]->hostname)) {
264258945Sroberto
265258945Sroberto			free(kod_db[b]);
266258945Sroberto			kod_db[b] = NULL;
267258945Sroberto			error = 1;
268258945Sroberto			break;
269258945Sroberto		}
270258945Sroberto
271258945Sroberto		kod_db[b]->timestamp = (time_t)ull;
272258945Sroberto	}
273258945Sroberto
274258945Sroberto	if (ferror(db_s) || error) {
275258945Sroberto		kod_db_cnt = b;
276258945Sroberto		msyslog(LOG_WARNING, "An error occured while parsing the KoD db file %s",
277258945Sroberto			db_file);
278258945Sroberto		fclose(db_s);
279258945Sroberto
280258945Sroberto		return;
281258945Sroberto	}
282258945Sroberto
283258945Sroberto	fclose(db_s);
284258945Sroberto#ifdef DEBUG
285258945Sroberto	for (a = 0; a < kod_db_cnt; a++)
286258945Sroberto		printf("KoD entry %d: %s at %llx type %s\n", a,
287258945Sroberto		       kod_db[a]->hostname,
288258945Sroberto		       (unsigned long long)kod_db[a]->timestamp,
289258945Sroberto		       kod_db[a]->type);
290258945Sroberto#endif
291258945Sroberto}
292