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