12b15cb3dSCy Schubert #include <config.h>
22b15cb3dSCy Schubert #include <string.h>
32b15cb3dSCy Schubert #include <sys/types.h>
42b15cb3dSCy Schubert #include <sys/stat.h>
52b15cb3dSCy Schubert
62b15cb3dSCy Schubert #include "kod_management.h"
72b15cb3dSCy Schubert #include "log.h"
82b15cb3dSCy Schubert #include "sntp-opts.h"
92b15cb3dSCy Schubert #include "ntp_stdlib.h"
102b15cb3dSCy Schubert #include "ntp_worker.h"
112b15cb3dSCy Schubert #include "ntp_debug.h"
122b15cb3dSCy Schubert
132b15cb3dSCy Schubert int kod_init = 0, kod_db_cnt = 0;
142b15cb3dSCy Schubert const char *kod_db_file;
152b15cb3dSCy Schubert struct kod_entry **kod_db; /* array of pointers to kod_entry */
162b15cb3dSCy Schubert
172b15cb3dSCy Schubert
182b15cb3dSCy Schubert /*
192b15cb3dSCy Schubert * Search for a KOD entry
202b15cb3dSCy Schubert */
212b15cb3dSCy Schubert int
search_entry(const char * hostname,struct kod_entry ** dst)222b15cb3dSCy Schubert search_entry(
232b15cb3dSCy Schubert const char *hostname,
242b15cb3dSCy Schubert struct kod_entry **dst
252b15cb3dSCy Schubert )
262b15cb3dSCy Schubert {
272b15cb3dSCy Schubert register int a, b, resc = 0;
282b15cb3dSCy Schubert
292b15cb3dSCy Schubert for (a = 0; a < kod_db_cnt; a++)
302b15cb3dSCy Schubert if (!strcmp(kod_db[a]->hostname, hostname))
312b15cb3dSCy Schubert resc++;
322b15cb3dSCy Schubert
332b15cb3dSCy Schubert if (!resc) {
342b15cb3dSCy Schubert *dst = NULL;
352b15cb3dSCy Schubert return 0;
362b15cb3dSCy Schubert }
372b15cb3dSCy Schubert
38276da39aSCy Schubert *dst = eallocarray(resc, sizeof(**dst));
392b15cb3dSCy Schubert
402b15cb3dSCy Schubert b = 0;
412b15cb3dSCy Schubert for (a = 0; a < kod_db_cnt; a++)
422b15cb3dSCy Schubert if (!strcmp(kod_db[a]->hostname, hostname)) {
432b15cb3dSCy Schubert (*dst)[b] = *kod_db[a];
442b15cb3dSCy Schubert b++;
452b15cb3dSCy Schubert }
462b15cb3dSCy Schubert
472b15cb3dSCy Schubert return resc;
482b15cb3dSCy Schubert }
492b15cb3dSCy Schubert
502b15cb3dSCy Schubert
512b15cb3dSCy Schubert void
add_entry(const char * hostname,const char * type)522b15cb3dSCy Schubert add_entry(
532b15cb3dSCy Schubert const char * hostname,
542b15cb3dSCy Schubert const char * type /* 4 bytes not \0 terminated */
552b15cb3dSCy Schubert )
562b15cb3dSCy Schubert {
572b15cb3dSCy Schubert int n;
582b15cb3dSCy Schubert struct kod_entry *pke;
592b15cb3dSCy Schubert
602b15cb3dSCy Schubert pke = emalloc_zero(sizeof(*pke));
612b15cb3dSCy Schubert pke->timestamp = time(NULL);
622b15cb3dSCy Schubert memcpy(pke->type, type, 4);
632b15cb3dSCy Schubert pke->type[sizeof(pke->type) - 1] = '\0';
642b15cb3dSCy Schubert strlcpy(pke->hostname, hostname, sizeof(pke->hostname));
652b15cb3dSCy Schubert
662b15cb3dSCy Schubert /*
672b15cb3dSCy Schubert * insert in address ("hostname") order to find duplicates
682b15cb3dSCy Schubert */
692b15cb3dSCy Schubert for (n = 0; n < kod_db_cnt; n++)
702b15cb3dSCy Schubert if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0)
712b15cb3dSCy Schubert break;
722b15cb3dSCy Schubert
732b15cb3dSCy Schubert if (n < kod_db_cnt &&
742b15cb3dSCy Schubert 0 == strcmp(kod_db[n]->hostname, pke->hostname)) {
752b15cb3dSCy Schubert kod_db[n]->timestamp = pke->timestamp;
762b15cb3dSCy Schubert free(pke);
772b15cb3dSCy Schubert return;
782b15cb3dSCy Schubert }
792b15cb3dSCy Schubert
802b15cb3dSCy Schubert kod_db_cnt++;
812b15cb3dSCy Schubert kod_db = erealloc(kod_db, kod_db_cnt * sizeof(kod_db[0]));
822b15cb3dSCy Schubert if (n != kod_db_cnt - 1)
832b15cb3dSCy Schubert memmove(&kod_db[n + 1], &kod_db[n],
842b15cb3dSCy Schubert sizeof(kod_db[0]) * ((kod_db_cnt - 1) - n));
852b15cb3dSCy Schubert kod_db[n] = pke;
862b15cb3dSCy Schubert }
872b15cb3dSCy Schubert
882b15cb3dSCy Schubert
892b15cb3dSCy Schubert void
delete_entry(const char * hostname,const char * type)902b15cb3dSCy Schubert delete_entry(
912b15cb3dSCy Schubert const char * hostname,
922b15cb3dSCy Schubert const char * type
932b15cb3dSCy Schubert )
942b15cb3dSCy Schubert {
952b15cb3dSCy Schubert int a;
962b15cb3dSCy Schubert
972b15cb3dSCy Schubert for (a = 0; a < kod_db_cnt; a++)
982b15cb3dSCy Schubert if (!strcmp(kod_db[a]->hostname, hostname)
992b15cb3dSCy Schubert && !strcmp(kod_db[a]->type, type))
1002b15cb3dSCy Schubert break;
1012b15cb3dSCy Schubert
1022b15cb3dSCy Schubert if (a == kod_db_cnt)
1032b15cb3dSCy Schubert return;
1042b15cb3dSCy Schubert
1052b15cb3dSCy Schubert free(kod_db[a]);
1062b15cb3dSCy Schubert kod_db_cnt--;
1072b15cb3dSCy Schubert
1082b15cb3dSCy Schubert if (a < kod_db_cnt)
1092b15cb3dSCy Schubert memmove(&kod_db[a], &kod_db[a + 1],
1102b15cb3dSCy Schubert (kod_db_cnt - a) * sizeof(kod_db[0]));
1112b15cb3dSCy Schubert }
1122b15cb3dSCy Schubert
1132b15cb3dSCy Schubert
1142b15cb3dSCy Schubert void
atexit_write_kod_db(void)1152b15cb3dSCy Schubert atexit_write_kod_db(void)
1162b15cb3dSCy Schubert {
1172b15cb3dSCy Schubert #ifdef WORK_FORK
1182b15cb3dSCy Schubert if (worker_process)
1192b15cb3dSCy Schubert return;
1202b15cb3dSCy Schubert #endif
1212b15cb3dSCy Schubert write_kod_db();
1222b15cb3dSCy Schubert }
1232b15cb3dSCy Schubert
1242b15cb3dSCy Schubert
1252b15cb3dSCy Schubert int
write_kod_db(void)1262b15cb3dSCy Schubert write_kod_db(void)
1272b15cb3dSCy Schubert {
1282b15cb3dSCy Schubert FILE *db_s;
1292b15cb3dSCy Schubert char *pch;
1302b15cb3dSCy Schubert int dirmode;
1312b15cb3dSCy Schubert register int a;
1322b15cb3dSCy Schubert
1332b15cb3dSCy Schubert db_s = fopen(kod_db_file, "w");
1342b15cb3dSCy Schubert
1352b15cb3dSCy Schubert /*
1362b15cb3dSCy Schubert * If opening fails, blindly attempt to create each directory
1372b15cb3dSCy Schubert * in the path first, then retry the open.
1382b15cb3dSCy Schubert */
1392b15cb3dSCy Schubert if (NULL == db_s && strlen(kod_db_file)) {
1402b15cb3dSCy Schubert dirmode = S_IRUSR | S_IWUSR | S_IXUSR
1412b15cb3dSCy Schubert | S_IRGRP | S_IXGRP
1422b15cb3dSCy Schubert | S_IROTH | S_IXOTH;
1432b15cb3dSCy Schubert pch = strchr(kod_db_file + 1, DIR_SEP);
1442b15cb3dSCy Schubert while (NULL != pch) {
1452b15cb3dSCy Schubert *pch = '\0';
1462b15cb3dSCy Schubert if (-1 == mkdir(kod_db_file, dirmode)
1472b15cb3dSCy Schubert && errno != EEXIST) {
1482b15cb3dSCy Schubert msyslog(LOG_ERR, "mkdir(%s) failed: %m",
1492b15cb3dSCy Schubert kod_db_file);
1502b15cb3dSCy Schubert return FALSE;
1512b15cb3dSCy Schubert }
1522b15cb3dSCy Schubert *pch = DIR_SEP;
1532b15cb3dSCy Schubert pch = strchr(pch + 1, DIR_SEP);
1542b15cb3dSCy Schubert }
1552b15cb3dSCy Schubert db_s = fopen(kod_db_file, "w");
1562b15cb3dSCy Schubert }
1572b15cb3dSCy Schubert
1582b15cb3dSCy Schubert if (NULL == db_s) {
1592b15cb3dSCy Schubert msyslog(LOG_WARNING, "Can't open KOD db file %s for writing: %m",
1602b15cb3dSCy Schubert kod_db_file);
1612b15cb3dSCy Schubert
1622b15cb3dSCy Schubert return FALSE;
1632b15cb3dSCy Schubert }
1642b15cb3dSCy Schubert
1652b15cb3dSCy Schubert for (a = 0; a < kod_db_cnt; a++) {
1662b15cb3dSCy Schubert fprintf(db_s, "%16.16llx %s %s\n", (unsigned long long)
1672b15cb3dSCy Schubert kod_db[a]->timestamp, kod_db[a]->type,
1682b15cb3dSCy Schubert kod_db[a]->hostname);
1692b15cb3dSCy Schubert }
1702b15cb3dSCy Schubert
1712b15cb3dSCy Schubert fflush(db_s);
1722b15cb3dSCy Schubert fclose(db_s);
1732b15cb3dSCy Schubert
1742b15cb3dSCy Schubert return TRUE;
1752b15cb3dSCy Schubert }
1762b15cb3dSCy Schubert
1772b15cb3dSCy Schubert
1782b15cb3dSCy Schubert void
kod_init_kod_db(const char * db_file,int readonly)1792b15cb3dSCy Schubert kod_init_kod_db(
1802b15cb3dSCy Schubert const char * db_file,
1812b15cb3dSCy Schubert int readonly
1822b15cb3dSCy Schubert )
1832b15cb3dSCy Schubert {
1842b15cb3dSCy Schubert /*
1852b15cb3dSCy Schubert * Max. of 254 characters for hostname, 10 for timestamp, 4 for
1862b15cb3dSCy Schubert * kisscode, 2 for spaces, 1 for \n, and 1 for \0
1872b15cb3dSCy Schubert */
1882b15cb3dSCy Schubert char fbuf[254+10+4+2+1+1];
1892b15cb3dSCy Schubert FILE *db_s;
1902b15cb3dSCy Schubert int a, b, sepc, len;
1912b15cb3dSCy Schubert unsigned long long ull;
1922b15cb3dSCy Schubert char *str_ptr;
1932b15cb3dSCy Schubert char error = 0;
1942b15cb3dSCy Schubert
1952b15cb3dSCy Schubert TRACE(2, ("Initializing KOD DB...\n"));
1962b15cb3dSCy Schubert
1972b15cb3dSCy Schubert kod_db_file = estrdup(db_file);
1982b15cb3dSCy Schubert
1992b15cb3dSCy Schubert db_s = fopen(db_file, "r");
2002b15cb3dSCy Schubert
2012b15cb3dSCy Schubert if (NULL == db_s) {
2022b15cb3dSCy Schubert msyslog(LOG_WARNING, "kod_init_kod_db(): Cannot open KoD db file %s: %m",
2032b15cb3dSCy Schubert db_file);
2042b15cb3dSCy Schubert
2052b15cb3dSCy Schubert return;
2062b15cb3dSCy Schubert }
2072b15cb3dSCy Schubert
2082b15cb3dSCy Schubert if (debug)
2092b15cb3dSCy Schubert printf("Starting to read KoD file %s...\n", db_file);
2102b15cb3dSCy Schubert /* First let's see how many entries there are and check for right syntax */
2112b15cb3dSCy Schubert
2122b15cb3dSCy Schubert while (!feof(db_s) && NULL != fgets(fbuf, sizeof(fbuf), db_s)) {
2132b15cb3dSCy Schubert
2142b15cb3dSCy Schubert /* ignore blank lines */
2152b15cb3dSCy Schubert if ('\n' == fbuf[0])
2162b15cb3dSCy Schubert continue;
2172b15cb3dSCy Schubert
2182b15cb3dSCy Schubert sepc = 0;
2192b15cb3dSCy Schubert len = strlen(fbuf);
2202b15cb3dSCy Schubert for (a = 0; a < len; a++) {
2212b15cb3dSCy Schubert if (' ' == fbuf[a])
2222b15cb3dSCy Schubert sepc++;
2232b15cb3dSCy Schubert
2242b15cb3dSCy Schubert if ('\n' == fbuf[a]) {
2252b15cb3dSCy Schubert if (sepc != 2) {
2262b15cb3dSCy Schubert if (strcmp(db_file, "/dev/null"))
2272b15cb3dSCy Schubert msyslog(LOG_DEBUG,
2282b15cb3dSCy Schubert "Syntax error in KoD db file %s in line %i (missing space)",
2292b15cb3dSCy Schubert db_file,
2302b15cb3dSCy Schubert kod_db_cnt + 1);
2312b15cb3dSCy Schubert fclose(db_s);
2322b15cb3dSCy Schubert return;
2332b15cb3dSCy Schubert }
2342b15cb3dSCy Schubert sepc = 0;
2352b15cb3dSCy Schubert kod_db_cnt++;
2362b15cb3dSCy Schubert }
2372b15cb3dSCy Schubert }
2382b15cb3dSCy Schubert }
2392b15cb3dSCy Schubert
2402b15cb3dSCy Schubert if (0 == kod_db_cnt) {
2412b15cb3dSCy Schubert TRACE(2, ("KoD DB %s empty.\n", db_file));
2422b15cb3dSCy Schubert goto wrapup;
2432b15cb3dSCy Schubert }
2442b15cb3dSCy Schubert
2452b15cb3dSCy Schubert TRACE(2, ("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt));
2462b15cb3dSCy Schubert
2472b15cb3dSCy Schubert rewind(db_s);
2482b15cb3dSCy Schubert
249*f0574f5cSXin LI /* Allocate the array of pointers to the struct kod_entry items */
250276da39aSCy Schubert kod_db = eallocarray(kod_db_cnt, sizeof(kod_db[0]));
2512b15cb3dSCy Schubert
2522b15cb3dSCy Schubert /* Read contents of file */
2532b15cb3dSCy Schubert for (b = 0;
2542b15cb3dSCy Schubert !feof(db_s) && !ferror(db_s) && b < kod_db_cnt;
2552b15cb3dSCy Schubert b++) {
2562b15cb3dSCy Schubert
2572b15cb3dSCy Schubert str_ptr = fgets(fbuf, sizeof(fbuf), db_s);
2582b15cb3dSCy Schubert if (NULL == str_ptr) {
2592b15cb3dSCy Schubert error = 1;
2602b15cb3dSCy Schubert break;
2612b15cb3dSCy Schubert }
2622b15cb3dSCy Schubert
2632b15cb3dSCy Schubert /* ignore blank lines */
2642b15cb3dSCy Schubert if ('\n' == fbuf[0]) {
2652b15cb3dSCy Schubert b--;
2662b15cb3dSCy Schubert continue;
2672b15cb3dSCy Schubert }
2682b15cb3dSCy Schubert
269*f0574f5cSXin LI /* Allocate this struct kod_entry item */
270*f0574f5cSXin LI kod_db[b] = emalloc(sizeof(*kod_db[0]));
2712b15cb3dSCy Schubert
2722b15cb3dSCy Schubert if (3 != sscanf(fbuf, "%llx %4s %254s", &ull,
2732b15cb3dSCy Schubert kod_db[b]->type, kod_db[b]->hostname)) {
2742b15cb3dSCy Schubert
2752b15cb3dSCy Schubert free(kod_db[b]);
2762b15cb3dSCy Schubert kod_db[b] = NULL;
2772b15cb3dSCy Schubert error = 1;
2782b15cb3dSCy Schubert break;
2792b15cb3dSCy Schubert }
2802b15cb3dSCy Schubert
2812b15cb3dSCy Schubert kod_db[b]->timestamp = (time_t)ull;
2822b15cb3dSCy Schubert }
2832b15cb3dSCy Schubert
2842b15cb3dSCy Schubert if (ferror(db_s) || error) {
2852b15cb3dSCy Schubert kod_db_cnt = b;
2862b15cb3dSCy Schubert msyslog(LOG_WARNING, "An error occured while parsing the KoD db file %s",
2872b15cb3dSCy Schubert db_file);
2882b15cb3dSCy Schubert fclose(db_s);
2892b15cb3dSCy Schubert
2902b15cb3dSCy Schubert return;
2912b15cb3dSCy Schubert }
2922b15cb3dSCy Schubert
2932b15cb3dSCy Schubert wrapup:
2942b15cb3dSCy Schubert fclose(db_s);
2952b15cb3dSCy Schubert for (a = 0; a < kod_db_cnt; a++)
2962b15cb3dSCy Schubert TRACE(2, ("KoD entry %d: %s at %llx type %s\n", a,
2972b15cb3dSCy Schubert kod_db[a]->hostname,
2982b15cb3dSCy Schubert (unsigned long long)kod_db[a]->timestamp,
2992b15cb3dSCy Schubert kod_db[a]->type));
3002b15cb3dSCy Schubert
3012b15cb3dSCy Schubert if (!readonly && write_kod_db())
3022b15cb3dSCy Schubert atexit(&atexit_write_kod_db);
3032b15cb3dSCy Schubert }
304