1 |
/* Licensed to the Apache Software Foundation (ASF) under one or more |
2 |
* contributor license agreements. See the NOTICE file distributed with |
3 |
* this work for additional information regarding copyright ownership. |
4 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
5 |
* (the "License"); you may not use this file except in compliance with |
6 |
* the License. You may obtain a copy of the License at |
7 |
* |
8 |
* http://www.apache.org/licenses/LICENSE-2.0 |
9 |
* |
10 |
* Unless required by applicable law or agreed to in writing, software |
11 |
* distributed under the License is distributed on an "AS IS" BASIS, |
12 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 |
* See the License for the specific language governing permissions and |
14 |
* limitations under the License. |
15 |
* |
16 |
* Originally developed by Aaron Bannert and Justin Erenkrantz, eBuilt. |
17 |
*/ |
18 |
|
19 |
#include <apr_general.h> /* For apr_initialize */ |
20 |
#include <apr_strings.h> |
21 |
#include <apr_file_io.h> |
22 |
#include <apr_pools.h> |
23 |
|
24 |
#if APR_HAVE_STDLIB_H |
25 |
#include <stdlib.h> /* rand/strtol */ |
26 |
#endif |
27 |
#if APR_HAVE_UNISTD_H |
28 |
#include <unistd.h> /* For pause */ |
29 |
#endif |
30 |
|
31 |
#include "config.h" |
32 |
#include "flood_profile.h" |
33 |
#include "flood_farm.h" |
34 |
#include "flood_farmer.h" |
35 |
#include "flood_config.h" |
36 |
|
37 |
#if FLOOD_HAS_OPENSSL |
38 |
#include "flood_net_ssl.h" /* For ssl_init_socket */ |
39 |
#endif /* FLOOD_HAS_OPENSSL */ |
40 |
|
41 |
/* Win32 doesn't have stdout or stderr. */ |
42 |
apr_file_t *local_stdin, *local_stdout, *local_stderr; |
43 |
|
44 |
/* Should be the new apr_sms_t struct? Not ready yet. */ |
45 |
apr_pool_t *local_pool; |
46 |
|
47 |
static apr_status_t set_seed(config_t *config) |
48 |
{ |
49 |
apr_status_t stat; |
50 |
struct apr_xml_elem *root_elem, *seed_elem; |
51 |
char *xml_seed = XML_SEED; |
52 |
unsigned int seed; |
53 |
|
54 |
/* get the root config node */ |
55 |
if ((stat = retrieve_root_xml_elem(&root_elem, config)) != APR_SUCCESS) { |
56 |
return stat; |
57 |
} |
58 |
|
59 |
/* get the seed node from config */ |
60 |
if ((stat = retrieve_xml_elem_child(&seed_elem, root_elem, xml_seed)) != APR_SUCCESS) { |
61 |
seed = 1; /* default if not found */ |
62 |
} |
63 |
else { |
64 |
if (seed_elem->first_cdata.first && seed_elem->first_cdata.first->text) { |
65 |
char *endptr; |
66 |
seed = (unsigned int) strtoll(seed_elem->first_cdata.first->text, |
67 |
&endptr, 10); |
68 |
if (*endptr != '\0') { |
69 |
apr_file_printf(local_stderr, |
70 |
"XML Node %s has invalid value '%s'.\n", |
71 |
XML_SEED, seed_elem->first_cdata.first->text); |
72 |
return APR_EGENERAL; |
73 |
} |
74 |
} |
75 |
else { |
76 |
seed = 1; |
77 |
} |
78 |
} |
79 |
|
80 |
/* actually set the seed */ |
81 |
#if FLOOD_USE_RAND |
82 |
srand(seed); |
83 |
#elif FLOOD_USE_RAND48 |
84 |
srand48(seed); |
85 |
#elif FLOOD_USE_RANDOM |
86 |
srandom(seed); |
87 |
#endif |
88 |
|
89 |
return APR_SUCCESS; |
90 |
} |
91 |
|
92 |
/* check if config file version matches flood config file version */ |
93 |
static apr_status_t check_versions(config_t *config) |
94 |
{ |
95 |
apr_status_t stat; |
96 |
char *endptr = NULL; |
97 |
apr_int64_t flood_version = 0; |
98 |
apr_int64_t config_version = 0; |
99 |
struct apr_xml_elem *root_elem; |
100 |
|
101 |
/* we assume that CONFIG_VERSION is sane */ |
102 |
flood_version = apr_strtoi64(CONFIG_VERSION, NULL, 0); |
103 |
|
104 |
/* get the root element */ |
105 |
if ((stat = retrieve_root_xml_elem(&root_elem, config)) != APR_SUCCESS) { |
106 |
return stat; |
107 |
} |
108 |
|
109 |
if (root_elem->attr) { |
110 |
apr_xml_attr *attr = root_elem->attr; |
111 |
while (attr) { |
112 |
if (!strncasecmp(attr->name, XML_FLOOD_CONFIG_VERSION, |
113 |
FLOOD_STRLEN_MAX)) { |
114 |
config_version = apr_strtoi64(attr->value, &endptr, 0); |
115 |
if (*endptr != '\0') { |
116 |
apr_file_printf(local_stderr, |
117 |
"invalid config version '%s'.\n", |
118 |
attr->value); |
119 |
return APR_EGENERAL; |
120 |
} |
121 |
} |
122 |
attr = attr->next; |
123 |
} |
124 |
} |
125 |
|
126 |
if (config_version != flood_version) { |
127 |
apr_file_printf(local_stderr, |
128 |
"your config file version '%lli' doesn't match flood config file version '%lli'.\n", |
129 |
config_version, flood_version); |
130 |
} |
131 |
|
132 |
return APR_SUCCESS; |
133 |
|
134 |
} |
135 |
|
136 |
int main(int argc, char** argv) |
137 |
{ |
138 |
apr_status_t stat; |
139 |
config_t *config; |
140 |
|
141 |
/* FIXME: Where is Roy's change to return the global pool... */ |
142 |
apr_initialize(); |
143 |
atexit(apr_terminate); |
144 |
|
145 |
apr_pool_create(&local_pool, NULL); |
146 |
|
147 |
#if FLOOD_HAS_OPENSSL |
148 |
/* FIXME: HHAAAAAAAAAAAAAAACCCCCCCCCCCKKKKKKKKKKK! */ |
149 |
/* Should be a run-time option with SSL, but Justin hates singleton. */ |
150 |
ssl_init_socket(local_pool); |
151 |
#endif /* FLOOD_HAS_OPENSSL */ |
152 |
|
153 |
apr_file_open_stdout(&local_stdout, local_pool); |
154 |
apr_file_open_stderr(&local_stderr, local_pool); |
155 |
|
156 |
if (argc == 1) { |
157 |
apr_file_open_stdin(&local_stdin, local_pool); |
158 |
} |
159 |
else if ((stat = apr_file_open(&local_stdin, argv[1], APR_READ, |
160 |
APR_OS_DEFAULT, local_pool)) != APR_SUCCESS) |
161 |
{ |
162 |
char buf[256]; |
163 |
apr_strerror(stat, (char*) &buf, sizeof(buf)); |
164 |
apr_file_printf(local_stderr, |
165 |
"Error opening configuration file: %s.\n", |
166 |
(char*)&buf); |
167 |
exit(-1); |
168 |
} |
169 |
|
170 |
/* parse the config */ |
171 |
config = parse_config(local_stdin, local_pool); |
172 |
|
173 |
if ((stat = set_seed(config)) != APR_SUCCESS) { |
174 |
char buf[256]; |
175 |
apr_strerror(stat, (char*) &buf, 256); |
176 |
apr_file_printf(local_stderr, "Error running test profile: %s.\n", |
177 |
(char*)&buf); |
178 |
exit(-1); |
179 |
} |
180 |
|
181 |
if ((stat = check_versions(config)) != APR_SUCCESS) { |
182 |
exit(-1); |
183 |
} |
184 |
|
185 |
if ((stat = run_farm(config, "Bingo", local_pool)) != APR_SUCCESS) { |
186 |
char buf[256]; |
187 |
apr_strerror(stat, (char*) &buf, 256); |
188 |
apr_file_printf(local_stderr, "Error running test profile: %s.\n", |
189 |
(char*)&buf); |
190 |
exit(-1); |
191 |
} |
192 |
|
193 |
/* report results -- for now just print results to stdout */ |
194 |
|
195 |
return EXIT_SUCCESS; |
196 |
} |