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