00001
#include <ctime>
00002
#include <stdio.h>
00003
#include <regex.h>
00004
#include <ctype.h>
00005
#include "unigremlin.h"
00006
00007 #define MAX_DEPTH 5
00008 #define TYPE_STRING 0
00009 #define TYPE_IP 1
00010 #define TYPE_IP_NETWORK 2
00011 #define TYPE_HOSTNAME 3
00012 #define TYPE_BOOL 4
00013 #define TYPE_INT 5
00014 #define TYPE_FLOAT 6
00015 #define NUM_TYPES 7
00016
00017 VictimDict UniConfGremlin::victims(500);
00018
00019 UniConfGremlin::UniConfGremlin(
WvString moniker,
const UniConfKey _key,
00020
int _max_runlevel)
00021 : cfg(moniker), key(_key), max_runlevel(_max_runlevel)
00022 {
00023 runlevel = 1;
00024 num_victims = 0;
00025
if (max_runlevel > 5 || max_runlevel < 1)
00026 max_runlevel = 4;
00027 }
00028
00029
00030
00031
00032
00033 void UniConfGremlin::start(
unsigned int seed)
00034 {
00035
if (seed == 0)
00036 seed = time(0);
00037
00038 srand(seed);
00039 printf(
"Using seed %i\n", seed);
00040 find_victims(key);
00041
for (runlevel = 1; runlevel <= max_runlevel; runlevel ++)
00042 start_trouble(runlevel);
00043 runlevel = max_runlevel - 1;
00044 }
00045
00046
00047
00048
00049
00050
00051
void UniConfGremlin::find_victims(
UniConfKey _key)
00052 {
00053 UniConf::Iter i(cfg[_key]);
00054
Victim *victim;
00055
for (i.rewind(); i.next(); )
00056 {
00057
if (i().get() ==
"")
00058 find_victims(i().fullkey());
00059
else
00060 {
00061 victim =
new Victim(num_victims, inspect(i().get()), i().fullkey());
00062 victims.add(victim,
true);
00063 num_victims ++;
00064 }
00065 }
00066 }
00067
00068
00069
00070
00071
00072
00073
int UniConfGremlin::inspect(
WvString element)
00074 {
00075
char *elem = element.
edit();
00076
00077
char *ipNetExp =
"[0-9].*\\.[0-9].*\\.[0-9].*\\.[0-9].*";
00078
if (is_bool(elem))
00079
return TYPE_BOOL;
00080
00081
if (isdigit(elem[0]))
00082 {
00083 regex_t preg1;
00084 regmatch_t pmatch1[1];
00085 regcomp(&preg1, ipNetExp, REG_EXTENDED | REG_NOSUB);
00086
00087
if (!regexec(&preg1, elem, 1, pmatch1, 0))
00088 {
00089
if (elem[element.
len() - 2] ==
'/' ||
00090 elem[element.
len() - 3] ==
'/')
00091
return TYPE_IP_NETWORK;
00092
else
00093
return TYPE_IP;
00094 }
00095 }
00096
00097
for (size_t i = 1; i < element.
len(); i++)
00098 {
00099
if (!isdigit(elem[i]))
00100
00101
return TYPE_STRING;
00102 }
00103
00104
return TYPE_INT;
00105 }
00106
00107
00108
00109
00110
bool UniConfGremlin::is_bool(
char *elem)
00111 {
00112
const char *strs[] = {
00113
"true",
"yes",
"on",
"enabled",
"1",
00114
"false",
"no",
"off",
"disabled",
"0"
00115 };
00116
00117
for (size_t i = 0; i <
sizeof(strs) /
sizeof(
const char*); ++i)
00118
if (strcasecmp(elem, strs[i]) == 0)
00119
return true;
00120
00121
return false;
00122 }
00123
00124
00125
00126
00127
00128
00129
void UniConfGremlin::change_value(
bool use_valid_data)
00130 {
00131
int r = num_victims + 1;
00132
while (r >= num_victims)
00133 {
00134 r = (
int)(((
double)rand() / (
double)RAND_MAX) * (num_victims));
00135 }
00136 last_change =
WvString(
"Changed %s to be the value", victims[r]->name);
00137 WvString new_value;
00138
if (use_valid_data)
00139 {
00140
if (victims[r]->type ==
TYPE_INT)
00141 {
00142
int new_value = rand();
00143 cfg[victims[r]->name].setint(new_value);
00144 last_change = WvString(
"%s %s\n", last_change, new_value);
00145 }
00146
else
00147 {
00148 WvString new_value = rand_str(victims[r]->type);
00149 cfg[victims[r]->name].set(new_value);
00150 last_change = WvString(
"%s %s\n", last_change, new_value);
00151 }
00152 }
00153
else
00154 {
00155
int s = (
int)(((
double)rand() / (
double)RAND_MAX) * 2);
00156
if (s)
00157 {
00158
int new_value = rand();
00159 cfg[victims[r]->name].setint(rand());
00160 last_change = WvString(
"%s %s\n", last_change, new_value);
00161 }
00162
else
00163 {
00164 WvString new_value = rand_str(victims[r]->type);
00165
int t = (
int)(((
double)rand() / (
double)RAND_MAX) *
NUM_TYPES);
00166 cfg[victims[r]->name].set(rand_str(t));
00167 last_change = WvString(
"%s %s\n", last_change, new_value);
00168 }
00169
00170 }
00171 cfg[victims[r]->name].commit();
00172
00173 }
00174
00175
00176
00177
00178
00179
void UniConfGremlin::add_value()
00180 {
00181
int depth = (
int)(((
double)rand() / (
double)RAND_MAX) *
MAX_DEPTH);
00182 WvString key_name =
"", elem;
00183
00184
00185
for (
int i = 0; i < depth; i++)
00186 {
00187 elem =
"";
00188
int length = (
int)(((
double)rand() / (
double)RAND_MAX) * 8);
00189
for (
int j = 0; j < length; j++)
00190 {
00191
00192
int num = (
int)((((
double)rand() / (
double)RAND_MAX) * 25)
00193 + 97);
00194
char c[2];
00195 c[0] = (
char)num;
00196 c[1] =
'\0';
00197 elem = WvString(
"%s%s", elem, c);
00198 }
00199
if (i > 0)
00200 key_name = WvString(
"%s/%s", key_name, elem);
00201
else
00202 key_name = elem;
00203 }
00204 key_name = WvString(
"%s/%s", key, key_name);
00205
00206 last_change = WvString(
"Added the key %s with the new value", key_name);
00207
00208
int num = (
int)((
double)rand() / (
double)RAND_MAX);
00209 Victim *victim;
00210
if (num)
00211
00212 {
00213
int new_value = rand();
00214 cfg[key_name].setint(new_value);
00215 victim =
new Victim(num_victims, TYPE_INT, key_name);
00216 last_change = WvString(
"%s %s\n", last_change, new_value);
00217 }
00218
else
00219
00220 {
00221
int type = (
int)(((
double)rand() / (
double)RAND_MAX) * 5
00222 +
TYPE_STRING);
00223 WvString new_value = rand_str(type);
00224 cfg[key_name].set(new_value);
00225 victim =
new Victim(num_victims, TYPE_STRING, key_name);
00226 last_change = WvString(
"%s %s\n", last_change, new_value);
00227 }
00228 victims.add(victim,
true);
00229 num_victims ++;
00230 cfg[key_name].commit();
00231 }
00232
00233
00234
00235
00236
00237
void UniConfGremlin::start_trouble(
int curr_runlevel)
00238 {
00239 printf(
"%s\n", UniConfGremlin::curr_runlevel().cstr());
00240
int r = curr_runlevel;
00241
for (
int i = 0; i < 1000; i ++)
00242 {
00243
if (curr_runlevel == 5)
00244 r = (
int)(((
double)rand() / (
double)RAND_MAX) * 4) + 1;
00245
00246
if (r == 1)
00247 change_value(
true);
00248
else if (r == 2)
00249 change_value(
false);
00250
else if (r == 3)
00251 add_value();
00252
else if (r >= 4)
00253
00254 {
00255
int r = (
int)(((
double)rand() / (
double)RAND_MAX) * (num_victims));
00256 cfg[victims[r]->name].remove();
00257 cfg[victims[r]->name].commit();
00258 last_change = WvString(
"Deleted the key %s\n", victims[r]->name);
00259 }
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270 WvString UniConfGremlin::rand_str(
int type)
00271 {
00272
if (type ==
TYPE_STRING || type ==
TYPE_HOSTNAME)
00273 {
00274
int a = (
int)(((
double)rand() / (
double)RAND_MAX) * 200);
00275 WvString result =
"";
00276
for (
int i = 0; i < a; i++)
00277 {
00278
int b = (
int)((((
double)rand() / (
double)RAND_MAX) * 26) + 97);
00279
char c[2];
00280 c[0] = (
char)b;
00281 c[1] =
'\0';
00282 result = WvString(
"%s%s", result, c);
00283 }
00284
return WvString(
"%s", result);
00285 }
00286
else if (type ==
TYPE_BOOL)
00287 {
00288
const char *strs[] = {
00289
"true",
"yes",
"on",
"enabled",
"1",
00290
"false",
"no",
"off",
"disabled",
"0"
00291 };
00292
int a = (
int)(((
double)rand() / (
double)RAND_MAX) * 10);
00293
return WvString(
"%s", strs[a]);
00294 }
00295
else if (type ==
TYPE_IP || type ==
TYPE_IP_NETWORK)
00296 {
00297
int a = (
int)(((
double)rand() / (
double)RAND_MAX) * 256),
00298 b = (
int)(((
double)rand() / (
double)RAND_MAX) * 256),
00299 c = (
int)(((
double)rand() / (
double)RAND_MAX) * 256),
00300 d = (
int)(((
double)rand() / (
double)RAND_MAX) * 256);
00301
if (type ==
TYPE_IP_NETWORK)
00302 {
00303
int e = (
int)(((
double)rand() / (
double)RAND_MAX) * 33);
00304
return WvString(
"%s.%s.%s.%s/%s", a, b, c, d, e);
00305 }
00306
else
00307
return WvString(
"%s.%s.%s.%s", a, b, c, d);
00308 }
00309
else if (type ==
TYPE_INT)
00310
return rand();
00311
else if (type ==
TYPE_FLOAT)
00312
return rand();
00313
else
00314
return "";
00315 }
00316
00317
00318
00319
00320 WvString UniConfGremlin::type_name(
int type)
00321 {
00322
if (type ==
TYPE_STRING)
00323
return "String";
00324
else if (type ==
TYPE_IP)
00325
return "IP";
00326
else if (type ==
TYPE_IP_NETWORK)
00327
return "IP Network";
00328
else if (type ==
TYPE_HOSTNAME)
00329
return "Hostname";
00330
else if (type ==
TYPE_BOOL)
00331
return "Boolean";
00332
else if (type ==
TYPE_INT)
00333
return "Integer";
00334
else if (type ==
TYPE_FLOAT)
00335
return "Float";
00336
else
00337
return "Unknown";
00338 }
00339
00340
00341
00342
00343 WvString UniConfGremlin::curr_runlevel()
00344 {
00345
if (runlevel == 1)
00346
return "1 - Change keys with valid data.";
00347
else if (runlevel == 2)
00348
return "2 - Change keys with invalid data.";
00349
else if (runlevel == 3)
00350
return "3 - Add new keys.";
00351
else if (runlevel == 4)
00352
return "4 - Remove keys.";
00353
else if (runlevel == 5)
00354
return "5 - Add/Remove keys, change keys with valid/invalid data.";
00355
else
00356
return WvString(
"Apparently I'm on runlevel %s", runlevel);
00357 }
00358
00359
00360
00361
00362 WvString
UniConfGremlin::status()
00363 {
00364
return WvString(
"Last Runlevel was : %s\nLast Action was : %s",
00365 curr_runlevel(), last_change);
00366 }
00367
00368
00369
00370
00371 void UniConfGremlin::test()
00372 {
00373 printf(
"Testing Random Generators\n");
00374 printf(
"STRING %s\n", UniConfGremlin::rand_str(
TYPE_STRING).cstr());
00375 printf(
"IP %s\n", UniConfGremlin::rand_str(
TYPE_IP).cstr());
00376 printf(
"IP_NETWORK %s\n", UniConfGremlin::rand_str(
TYPE_IP_NETWORK).cstr());
00377 printf(
"HOSTNAME %s\n", UniConfGremlin::rand_str(
TYPE_HOSTNAME).cstr());
00378 printf(
"BOOL %s\n", UniConfGremlin::rand_str(
TYPE_BOOL).cstr());
00379 printf(
"INT %s\n", UniConfGremlin::rand_str(
TYPE_INT).cstr());
00380 printf(
"FLOAT %s\n", UniConfGremlin::rand_str(
TYPE_FLOAT).cstr());
00381 printf(
"Testing adding things to the UniConf\n");
00382
int count = 0;
00383
for (
int i = 0; i < 5; i ++)
00384 {
00385 printf(
"Adding 5 random strings of type %s\n", type_name(i).cstr());
00386
for (
int j = 0; j < 5; j ++)
00387 {
00388 WvString rand = rand_str(i);
00389 printf(
"Adding %s\n", rand.
cstr());
00390 cfg[count].set(rand);
00391 cfg[count].commit();
00392 count ++;
00393 }
00394 }
00395 printf(
"Adding 5 random ints\n");
00396
for (
int i = 5; i < 10; i ++)
00397 {
00398
int randint = rand();
00399 printf(
"Adding %i\n", randint);
00400 cfg[count].setint(randint);
00401 cfg[count].commit();
00402 count ++;
00403 }
00404 printf(
"Testing Find Victims\n");
00405 find_victims(key);
00406
for (
int i = 0; i < num_victims; i ++)
00407 {
00408 printf(
"%s:", victims[i]->name.cstr());
00409 printf(
"%s:", type_name(victims[i]->type).cstr());
00410 printf(
"%s\n", cfg[victims[i]->name].get().cstr());
00411 }
00412
00413 printf(
"Testing Start Trouble\n");
00414 start_trouble(1);
00415 }