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