-
Notifications
You must be signed in to change notification settings - Fork 1
/
fds.c
166 lines (137 loc) · 2.95 KB
/
fds.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "shm.h"
#include "files.h"
#include "pids.h"
#include "net.h"
#include "log.h"
#include "params.h"
unsigned int nr_file_fds = 0;
static void open_pipes(void)
{
int pipes[2];
unsigned int i;
for (i = 0; i < MAX_PIPE_FDS; i+=2) {
if (pipe(pipes) < 0) {
perror("pipe fail.\n");
exit(EXIT_FAILURE);
}
shm->pipe_fds[i] = pipes[0];
shm->pipe_fds[i+1] = pipes[1];
output(2, "fd[%d] = pipe\n", shm->pipe_fds[i]);
output(2, "fd[%d] = pipe\n", shm->pipe_fds[i+1]);
}
}
static int get_new_random_fd(void)
{
unsigned int i;
unsigned int fd_index;
FILE *file;
int fd = 0;
int ret;
i = rand() % 3;
if (do_specific_proto == TRUE)
i = 1;
if (no_files == TRUE)
i = 1;
/* Ugly special case.
* Sometimes, we can get here without any fd's setup.
* If this happens, we divide by zero if we pick case 0 because
* nr_file_fds is zero
*
* When this circumstance occurs, we just force it to use another network socket.
*
* FIXME: A better solution would be to like, actually open an fd. duh.
*/
if (nr_file_fds == 0)
i = 1;
switch (i) {
case 0:
retry_file:
fd_index = rand() % nr_file_fds;
fd = shm->file_fds[fd_index];
/* avoid stdin/stdout/stderr */
if (logging == FALSE)
ret = fileno(stderr);
/* if logging is enabled, we want to make sure we skip
* over the logfiles, so get highest logfile fd. */
else {
file = shm->logfiles[shm->max_children - 1];
if (file == NULL) {
printf("## WTF, logfile was null!\n");
printf("## logfiles: ");
for_each_pidslot(i)
printf("%p ", shm->logfiles[i]);
printf("\n");
exit(EXIT_FAILURE);
}
ret = fileno(file);
if (ret == -1) {
BUG("fileno failed!");
printf("%s", strerror(errno));
exit(EXIT_FAILURE);
}
}
if (fd <= ret)
goto retry_file;
break;
case 1:
/* When using victim files, sockets can be 0.
* Use files as a fallback, or pipes if no files are open.
*/
if (nr_sockets == 0) {
if (nr_file_fds > 0)
goto retry_file;
else
goto do_pipe;
}
fd = shm->socket_fds[rand() % nr_sockets];
break;
case 2:
do_pipe:
fd = shm->pipe_fds[rand() % MAX_PIPE_FDS];
break;
default:
break;
}
return fd;
}
int get_random_fd(void)
{
/* 25% chance of returning something new. */
if ((rand() % 4) == 0)
return get_new_random_fd();
/* the rest of the time, return the same fd as last time. */
regen:
if (shm->fd_lifetime == 0) {
shm->current_fd = get_new_random_fd();
shm->fd_lifetime = (rand() % shm->max_children) + 5;
} else
shm->fd_lifetime--;
if (shm->current_fd == 0) {
shm->fd_lifetime = 0;
goto regen;
}
return shm->current_fd;
}
void setup_fds(void)
{
open_sockets();
if (no_files == TRUE)
return;
open_pipes();
generate_filelist();
if (files_in_index == 0)
return;
open_files();
}
void regenerate_fds(void)
{
if (no_files == TRUE)
return;
close_files();
open_files();
}