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