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