kod_management.c revision 280849
167555Smsmith#include <config.h> 267555Smsmith#include <string.h> 367555Smsmith#include <sys/types.h> 467555Smsmith#include <sys/stat.h> 567555Smsmith 667555Smsmith#include "kod_management.h" 767555Smsmith#include "log.h" 867555Smsmith#include "sntp-opts.h" 967555Smsmith#include "ntp_stdlib.h" 1067555Smsmith#include "ntp_worker.h" 1167555Smsmith#include "ntp_debug.h" 1267555Smsmith 1367555Smsmithint kod_init = 0, kod_db_cnt = 0; 1467555Smsmithconst char *kod_db_file; 1567555Smsmithstruct kod_entry **kod_db; /* array of pointers to kod_entry */ 1667555Smsmith 1767555Smsmith 1867555Smsmith/* 1967555Smsmith * Search for a KOD entry 2067555Smsmith */ 2167555Smsmithint 2267555Smsmithsearch_entry( 2367555Smsmith const char *hostname, 2467555Smsmith struct kod_entry **dst 2567555Smsmith ) 2667555Smsmith{ 2767555Smsmith register int a, b, resc = 0; 2867555Smsmith 2967555Smsmith for (a = 0; a < kod_db_cnt; a++) 3067555Smsmith if (!strcmp(kod_db[a]->hostname, hostname)) 3167555Smsmith resc++; 3267555Smsmith 3367555Smsmith if (!resc) { 3467555Smsmith *dst = NULL; 3567555Smsmith return 0; 3667555Smsmith } 3767555Smsmith 3867555Smsmith *dst = emalloc(resc * sizeof(**dst)); 3967555Smsmith 4067555Smsmith b = 0; 4167555Smsmith for (a = 0; a < kod_db_cnt; a++) 4267555Smsmith if (!strcmp(kod_db[a]->hostname, hostname)) { 4367555Smsmith (*dst)[b] = *kod_db[a]; 4467555Smsmith b++; 4567555Smsmith } 4667555Smsmith 4767555Smsmith return resc; 4867555Smsmith} 4967555Smsmith 5067555Smsmith 5167555Smsmithvoid 5267555Smsmithadd_entry( 5367555Smsmith const char * hostname, 5467555Smsmith const char * type /* 4 bytes not \0 terminated */ 5567555Smsmith ) 5667555Smsmith{ 5767555Smsmith int n; 5867555Smsmith struct kod_entry *pke; 5967555Smsmith 6067555Smsmith pke = emalloc_zero(sizeof(*pke)); 6167555Smsmith pke->timestamp = time(NULL); 6267555Smsmith memcpy(pke->type, type, 4); 6367555Smsmith pke->type[sizeof(pke->type) - 1] = '\0'; 6467555Smsmith strlcpy(pke->hostname, hostname, sizeof(pke->hostname)); 6567555Smsmith 6667555Smsmith /* 6767555Smsmith * insert in address ("hostname") order to find duplicates 6867555Smsmith */ 6967555Smsmith for (n = 0; n < kod_db_cnt; n++) 7067555Smsmith if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0) 7167555Smsmith break; 7267555Smsmith 7367555Smsmith if (n < kod_db_cnt && 7467555Smsmith 0 == strcmp(kod_db[n]->hostname, pke->hostname)) { 7567555Smsmith kod_db[n]->timestamp = pke->timestamp; 7667555Smsmith free(pke); 7767555Smsmith return; 7867555Smsmith } 7967555Smsmith 8067555Smsmith kod_db_cnt++; 8167555Smsmith kod_db = erealloc(kod_db, kod_db_cnt * sizeof(kod_db[0])); 8267555Smsmith if (n != kod_db_cnt - 1) 8367555Smsmith memmove(&kod_db[n + 1], &kod_db[n], 8467555Smsmith sizeof(kod_db[0]) * ((kod_db_cnt - 1) - n)); 8567555Smsmith kod_db[n] = pke; 8667555Smsmith} 8767555Smsmith 8867555Smsmith 8967555Smsmithvoid 9067555Smsmithdelete_entry( 9167555Smsmith const char * hostname, 9267555Smsmith const char * type 93118508Sps ) 94118508Sps{ 95118508Sps int a; 96118508Sps 97118508Sps for (a = 0; a < kod_db_cnt; a++) 98118508Sps if (!strcmp(kod_db[a]->hostname, hostname) 99118508Sps && !strcmp(kod_db[a]->type, type)) 100118508Sps break; 101118508Sps 102118508Sps if (a == kod_db_cnt) 103 return; 104 105 free(kod_db[a]); 106 kod_db_cnt--; 107 108 if (a < kod_db_cnt) 109 memmove(&kod_db[a], &kod_db[a + 1], 110 (kod_db_cnt - a) * sizeof(kod_db[0])); 111} 112 113 114void 115atexit_write_kod_db(void) 116{ 117#ifdef WORK_FORK 118 if (worker_process) 119 return; 120#endif 121 write_kod_db(); 122} 123 124 125int 126write_kod_db(void) 127{ 128 FILE *db_s; 129 char *pch; 130 int dirmode; 131 register int a; 132 133 db_s = fopen(kod_db_file, "w"); 134 135 /* 136 * If opening fails, blindly attempt to create each directory 137 * in the path first, then retry the open. 138 */ 139 if (NULL == db_s && strlen(kod_db_file)) { 140 dirmode = S_IRUSR | S_IWUSR | S_IXUSR 141 | S_IRGRP | S_IXGRP 142 | S_IROTH | S_IXOTH; 143 pch = strchr(kod_db_file + 1, DIR_SEP); 144 while (NULL != pch) { 145 *pch = '\0'; 146 if (-1 == mkdir(kod_db_file, dirmode) 147 && errno != EEXIST) { 148 msyslog(LOG_ERR, "mkdir(%s) failed: %m", 149 kod_db_file); 150 return FALSE; 151 } 152 *pch = DIR_SEP; 153 pch = strchr(pch + 1, DIR_SEP); 154 } 155 db_s = fopen(kod_db_file, "w"); 156 } 157 158 if (NULL == db_s) { 159 msyslog(LOG_WARNING, "Can't open KOD db file %s for writing: %m", 160 kod_db_file); 161 162 return FALSE; 163 } 164 165 for (a = 0; a < kod_db_cnt; a++) { 166 fprintf(db_s, "%16.16llx %s %s\n", (unsigned long long) 167 kod_db[a]->timestamp, kod_db[a]->type, 168 kod_db[a]->hostname); 169 } 170 171 fflush(db_s); 172 fclose(db_s); 173 174 return TRUE; 175} 176 177 178void 179kod_init_kod_db( 180 const char * db_file, 181 int readonly 182 ) 183{ 184 /* 185 * Max. of 254 characters for hostname, 10 for timestamp, 4 for 186 * kisscode, 2 for spaces, 1 for \n, and 1 for \0 187 */ 188 char fbuf[254+10+4+2+1+1]; 189 FILE *db_s; 190 int a, b, sepc, len; 191 unsigned long long ull; 192 char *str_ptr; 193 char error = 0; 194 195 TRACE(2, ("Initializing KOD DB...\n")); 196 197 kod_db_file = estrdup(db_file); 198 199 db_s = fopen(db_file, "r"); 200 201 if (NULL == db_s) { 202 msyslog(LOG_WARNING, "kod_init_kod_db(): Cannot open KoD db file %s: %m", 203 db_file); 204 205 return; 206 } 207 208 if (debug) 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 msyslog(LOG_DEBUG, 228 "Syntax error in KoD db file %s in line %i (missing space)", 229 db_file, 230 kod_db_cnt + 1); 231 fclose(db_s); 232 return; 233 } 234 sepc = 0; 235 kod_db_cnt++; 236 } 237 } 238 } 239 240 if (0 == kod_db_cnt) { 241 TRACE(2, ("KoD DB %s empty.\n", db_file)); 242 goto wrapup; 243 } 244 245 TRACE(2, ("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt)); 246 247 rewind(db_s); 248 249 kod_db = emalloc(sizeof(kod_db[0]) * kod_db_cnt); 250 251 /* Read contents of file */ 252 for (b = 0; 253 !feof(db_s) && !ferror(db_s) && b < kod_db_cnt; 254 b++) { 255 256 str_ptr = fgets(fbuf, sizeof(fbuf), db_s); 257 if (NULL == str_ptr) { 258 error = 1; 259 break; 260 } 261 262 /* ignore blank lines */ 263 if ('\n' == fbuf[0]) { 264 b--; 265 continue; 266 } 267 268 kod_db[b] = emalloc(sizeof(*kod_db[b])); 269 270 if (3 != sscanf(fbuf, "%llx %4s %254s", &ull, 271 kod_db[b]->type, kod_db[b]->hostname)) { 272 273 free(kod_db[b]); 274 kod_db[b] = NULL; 275 error = 1; 276 break; 277 } 278 279 kod_db[b]->timestamp = (time_t)ull; 280 } 281 282 if (ferror(db_s) || error) { 283 kod_db_cnt = b; 284 msyslog(LOG_WARNING, "An error occured while parsing the KoD db file %s", 285 db_file); 286 fclose(db_s); 287 288 return; 289 } 290 291 wrapup: 292 fclose(db_s); 293 for (a = 0; a < kod_db_cnt; a++) 294 TRACE(2, ("KoD entry %d: %s at %llx type %s\n", a, 295 kod_db[a]->hostname, 296 (unsigned long long)kod_db[a]->timestamp, 297 kod_db[a]->type)); 298 299 if (!readonly && write_kod_db()) 300 atexit(&atexit_write_kod_db); 301} 302