-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmain.cpp
203 lines (187 loc) · 6.69 KB
/
main.cpp
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <iostream>
#include <thread>
#include <atomic>
#include <cstring>
#include <signal.h>
#include "syslog_generator.hpp"
#include "trap_generator.hpp"
#include "netflow5_generator.hpp"
#include "netflow9_generator.hpp"
void daemonize();
void signal_callback_handler(int signum);
void SIGUSR1Handler(int signum);
int main(int argc, char **argv) {
const int HOST_LEN = 512;
char host[HOST_LEN];
memset(host, 0, HOST_LEN);
int port = -1;
int rate = -1;
char daemon = 0;
char interactive = 1;
int num_threads = -1;
unsigned int num_packets_per_send = 0;
unsigned int totalPackets = 0;
unsigned int totalSeconds = 0;
enum payloads {SNMP, SYSLOG, NETFLOW5, NETFLOW9} payload = SYSLOG;
int c;
while ((c = getopt(argc, argv, "dih:p:r:s:S:t:x:z:")) != -1) {
switch (c) {
case 'd':
daemon = 1;
break;
case 'i':
interactive = 0;
break;
case 'h':
strncpy(host, optarg, HOST_LEN);
break;
case 'p':
port = atoi(optarg);
break;
case 'r':
rate = atoi(optarg);
break;
case 's':
totalPackets = atoi(optarg);
break;
case 'S':
totalSeconds = atoi(optarg);
break;
case 't':
num_threads = atoi(optarg);
break;
case 'x':
if (strcmp(optarg, "snmp") == 0) {
payload = SNMP;
} else if (strcmp(optarg, "syslog") == 0) {
payload = SYSLOG;
} else if (strcmp(optarg, "netflow5") == 0) {
payload = NETFLOW5;
} else if (strcmp(optarg, "netflow9") == 0) {
payload = NETFLOW9;
} else {
printf("Invalid payload type: %s\n", optarg);
return 1;
}
break;
case 'z':
num_packets_per_send = atoi(optarg);
break;
default:
printf("\nUsage: udpgen [-d] [-i] [-h host] [-p port] [-r rate] [-t threads] [-z packets] [-x type]\n\n");
printf(" -x: Type of payload: snmp, syslog, netflow5, netflow9 (default: syslog)\n");
printf(" -d: Daemonize (default: false)\n");
printf(" -i: Disable interactivity (default: false)\n");
printf(" -h: Target host / IP address (default: 127.0.0.1)\n");
printf(" -p: Target port (default: depends on mode)\n");
printf(" -r: Rate - number of packets per second to generate (default: 10000)\n");
printf(" set the rate to 0 in order to disable rate limiting\n");
printf(" -t: Number of threads used to generate packets (default: 1)\n");
printf(" -z: Number of packets per iteration (default: 1)\n");
printf(" increase this when sending packets at a high rate\n\n");
return 1;
}
}
if (daemon) {
daemonize();
}
// Register signal & signal handler
signal(SIGINT, signal_callback_handler);
signal(SIGUSR1, SIGUSR1Handler);
std::unique_ptr<UDPGenerator> generator;
switch (payload) {
case SNMP: generator = std::unique_ptr<UDPGenerator>(new TrapGenerator()); break;
case SYSLOG: generator = std::unique_ptr<UDPGenerator>(new SyslogGenerator()); break;
case NETFLOW5: generator = std::unique_ptr<UDPGenerator>(new Netflow5Generator()); break;
case NETFLOW9: generator = std::unique_ptr<UDPGenerator>(new Netflow9Generator()); break;
}
if (strlen(host) > 0) {
generator->setHost(host);
}
if (port > 0) {
generator->setPort(port);
}
if (rate >= 0) {
generator->setPacketsPerSecond(rate);
}
if (totalPackets > 0) {
generator->setStopAfterPackets(totalPackets);
}
if (totalSeconds > 0) {
generator->setStopAfterSeconds(totalSeconds);
}
if (num_threads > 0) {
generator->setNumThreads(num_threads);
}
if (num_packets_per_send > 0) {
generator->setNumPacketsPerSend(num_packets_per_send);
}
if (generator->getPacketsPerSecond() > 10000 && generator->getNumPacketsPerSend() < 10) {
printf("\nWARNING: Packet rate limiting breaks down at high rates. "
"Consider increasing the number of packets per send.\n\n");
}
printf("Sending %s to %s:%d at target rate of %.2f packets per seconds across %d thread(s).\n",
generator->getPacketDescription(), generator->getHost(), generator->getPort(), generator->getPacketsPerSecond(),
generator->getNumThreads());
if (generator->getPacketsPerSecond() > 0) {
printf("\nThe number of packets sent should be printed every %d seconds.\n"
"If the more than %d seconds elapses between the reports, "
"the program is unable to generate packets at the requested rate.\n"
"Consider increasing the number of threads.\n\n",
generator->getReportInterval(), generator->getReportInterval());
}
std::cout << "Starting UDP generator..." << std::endl;
if (generator->start()) {
std::cout << "UDP generator startup failed. Exiting.." << std::endl;
return 1;
}
if (interactive && !totalPackets && !totalSeconds) {
char waitForKey;
std::cout << "Type q + enter to exit..." << std::endl;
std::cin >> waitForKey;
} else {
pause();
}
generator->stop();
return 0;
}
void daemonize() {
FILE *fp= NULL;
pid_t process_id = 0;
pid_t sid = 0;
// Create child process
process_id = fork();
// Indication of fork() failure
if (process_id < 0) {
printf("fork failed!\n");
// Return failure in exit status
std::exit(1);
}
// PARENT PROCESS. Need to kill it.
if (process_id > 0) {
printf("process_id of child process %d \n", process_id);
// return success in exit status
std::exit(0);
}
//unmask the file mode
//umask(0);
//set new session
sid = setsid();
if (sid < 0) {
// Return failure
std::exit(1);
}
// Change the current working directory to tmp.
chdir("/tmp");
// Close stdin. stdout and stderr
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
void signal_callback_handler(int signum) {
printf("Caught signal %d\n", signum);
exit(signum);
}
void SIGUSR1Handler(int signum) {
exit(0);
}