diff options
Diffstat (limited to 'plugins/check_fping.c')
-rw-r--r-- | plugins/check_fping.c | 1034 |
1 files changed, 544 insertions, 490 deletions
diff --git a/plugins/check_fping.c b/plugins/check_fping.c index 70d6f9fc..8018e06d 100644 --- a/plugins/check_fping.c +++ b/plugins/check_fping.c | |||
@@ -1,36 +1,36 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Monitoring check_fping plugin | 3 | * Monitoring check_fping plugin |
4 | * | 4 | * |
5 | * License: GPL | 5 | * License: GPL |
6 | * Copyright (c) 2000-2007 Monitoring Plugins Development Team | 6 | * Copyright (c) 2000-2024 Monitoring Plugins Development Team |
7 | * | 7 | * |
8 | * Description: | 8 | * Description: |
9 | * | 9 | * |
10 | * This file contains the check_disk plugin | 10 | * This file contains the check_fping plugin |
11 | * | 11 | * |
12 | * This plugin will use the fping command to ping the specified host for a | 12 | * This plugin will use the fping command to ping the specified host for a |
13 | * fast check | 13 | * fast check |
14 | * | 14 | * |
15 | * | 15 | * |
16 | * This program is free software: you can redistribute it and/or modify | 16 | * This program is free software: you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
18 | * the Free Software Foundation, either version 3 of the License, or | 18 | * the Free Software Foundation, either version 3 of the License, or |
19 | * (at your option) any later version. | 19 | * (at your option) any later version. |
20 | * | 20 | * |
21 | * This program is distributed in the hope that it will be useful, | 21 | * This program is distributed in the hope that it will be useful, |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
24 | * GNU General Public License for more details. | 24 | * GNU General Public License for more details. |
25 | * | 25 | * |
26 | * You should have received a copy of the GNU General Public License | 26 | * You should have received a copy of the GNU General Public License |
27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
28 | * | 28 | * |
29 | * | 29 | * |
30 | *****************************************************************************/ | 30 | *****************************************************************************/ |
31 | 31 | ||
32 | const char *progname = "check_fping"; | 32 | const char *progname = "check_fping"; |
33 | const char *copyright = "2000-2007"; | 33 | const char *copyright = "2000-2024"; |
34 | const char *email = "devel@monitoring-plugins.org"; | 34 | const char *email = "devel@monitoring-plugins.org"; |
35 | 35 | ||
36 | #include "common.h" | 36 | #include "common.h" |
@@ -38,490 +38,544 @@ const char *email = "devel@monitoring-plugins.org"; | |||
38 | #include "netutils.h" | 38 | #include "netutils.h" |
39 | #include "utils.h" | 39 | #include "utils.h" |
40 | #include <stdbool.h> | 40 | #include <stdbool.h> |
41 | #include "check_fping.d/config.h" | ||
42 | #include "states.h" | ||
41 | 43 | ||
42 | enum { | 44 | enum { |
43 | PACKET_COUNT = 1, | 45 | PL = 0, |
44 | PACKET_SIZE = 56, | 46 | RTA = 1 |
45 | PL = 0, | ||
46 | RTA = 1 | ||
47 | }; | 47 | }; |
48 | 48 | ||
49 | int textscan (char *buf); | 49 | static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/, double /*crta*/, bool /*wrta_p*/, double /*wrta*/, |
50 | int process_arguments (int, char **); | 50 | bool /*cpl_p*/, int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/); |
51 | int get_threshold (char *arg, char *rv[2]); | 51 | |
52 | void print_help (void); | 52 | typedef struct { |
53 | void print_usage (void); | 53 | int errorcode; |
54 | 54 | check_fping_config config; | |
55 | char *server_name = NULL; | 55 | } check_fping_config_wrapper; |
56 | char *sourceip = NULL; | 56 | static check_fping_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); |
57 | char *sourceif = NULL; | 57 | static int get_threshold(char *arg, char *rv[2]); |
58 | int packet_size = PACKET_SIZE; | 58 | static void print_help(void); |
59 | int packet_count = PACKET_COUNT; | 59 | void print_usage(void); |
60 | int target_timeout = 0; | 60 | |
61 | int packet_interval = 0; | 61 | static bool verbose = false; |
62 | bool verbose = false; | 62 | |
63 | int cpl; | 63 | int main(int argc, char **argv) { |
64 | int wpl; | 64 | setlocale(LC_ALL, ""); |
65 | double crta; | 65 | bindtextdomain(PACKAGE, LOCALEDIR); |
66 | double wrta; | 66 | textdomain(PACKAGE); |
67 | bool cpl_p = false; | 67 | |
68 | bool wpl_p = false; | 68 | /* Parse extra opts if any */ |
69 | bool alive_p = false; | 69 | argv = np_extra_opts(&argc, argv, progname); |
70 | bool crta_p = false; | 70 | |
71 | bool wrta_p = false; | 71 | check_fping_config_wrapper tmp_config = process_arguments(argc, argv); |
72 | 72 | if (tmp_config.errorcode == ERROR) { | |
73 | int | 73 | usage4(_("Could not parse arguments")); |
74 | main (int argc, char **argv) | 74 | } |
75 | { | 75 | |
76 | /* normally should be int result = STATE_UNKNOWN; */ | 76 | const check_fping_config config = tmp_config.config; |
77 | 77 | ||
78 | int status = STATE_UNKNOWN; | 78 | char *server = NULL; |
79 | int result = 0; | 79 | server = strscpy(server, config.server_name); |
80 | char *fping_prog = NULL; | 80 | |
81 | char *server = NULL; | 81 | char *option_string = ""; |
82 | char *command_line = NULL; | 82 | char *fping_prog = NULL; |
83 | char *input_buffer = NULL; | 83 | |
84 | char *option_string = ""; | 84 | /* First determine if the target is dualstack or ipv6 only. */ |
85 | input_buffer = malloc (MAX_INPUT_BUFFER); | 85 | bool server_is_inet6_addr = is_inet6_addr(server); |
86 | 86 | ||
87 | setlocale (LC_ALL, ""); | 87 | /* |
88 | bindtextdomain (PACKAGE, LOCALEDIR); | 88 | * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack |
89 | textdomain (PACKAGE); | 89 | * -> we use ipv6 |
90 | 90 | * If the user requested -4 OR the user made no assertion and the address is v4 ONLY | |
91 | /* Parse extra opts if any */ | 91 | * -> we use ipv4 |
92 | argv=np_extra_opts (&argc, argv, progname); | 92 | */ |
93 | 93 | if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) { | |
94 | if (process_arguments (argc, argv) == ERROR) | 94 | xasprintf(&option_string, "%s-6 ", option_string); |
95 | usage4 (_("Could not parse arguments")); | 95 | } else { |
96 | 96 | xasprintf(&option_string, "%s-4 ", option_string); | |
97 | server = strscpy (server, server_name); | 97 | } |
98 | 98 | fping_prog = strdup(PATH_TO_FPING); | |
99 | /* compose the command */ | 99 | |
100 | if (target_timeout) | 100 | /* compose the command */ |
101 | xasprintf(&option_string, "%s-t %d ", option_string, target_timeout); | 101 | if (config.target_timeout) { |
102 | if (packet_interval) | 102 | xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout); |
103 | xasprintf(&option_string, "%s-p %d ", option_string, packet_interval); | 103 | } |
104 | if (sourceip) | 104 | if (config.packet_interval) { |
105 | xasprintf(&option_string, "%s-S %s ", option_string, sourceip); | 105 | xasprintf(&option_string, "%s-p %d ", option_string, config.packet_interval); |
106 | if (sourceif) | 106 | } |
107 | xasprintf(&option_string, "%s-I %s ", option_string, sourceif); | 107 | if (config.sourceip) { |
108 | 108 | xasprintf(&option_string, "%s-S %s ", option_string, config.sourceip); | |
109 | #ifdef PATH_TO_FPING6 | 109 | } |
110 | if (address_family != AF_INET && is_inet6_addr(server)) | 110 | if (config.sourceif) { |
111 | fping_prog = strdup(PATH_TO_FPING6); | 111 | xasprintf(&option_string, "%s-I %s ", option_string, config.sourceif); |
112 | else | 112 | } |
113 | fping_prog = strdup(PATH_TO_FPING); | 113 | if (config.dontfrag) { |
114 | #else | 114 | xasprintf(&option_string, "%s-M ", option_string); |
115 | fping_prog = strdup(PATH_TO_FPING); | 115 | } |
116 | #endif | 116 | if (config.randomize_packet_data) { |
117 | 117 | xasprintf(&option_string, "%s-R ", option_string); | |
118 | xasprintf (&command_line, "%s %s-b %d -c %d %s", fping_prog, | 118 | } |
119 | option_string, packet_size, packet_count, server); | 119 | |
120 | 120 | if (config.fwmark_set) { | |
121 | if (verbose) | 121 | xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark); |
122 | printf ("%s\n", command_line); | 122 | } |
123 | 123 | ||
124 | /* run the command */ | 124 | if (config.icmp_timestamp) { |
125 | child_process = spopen (command_line); | 125 | xasprintf(&option_string, "%s--icmp-timestamp ", option_string); |
126 | if (child_process == NULL) { | 126 | } |
127 | printf (_("Could not open pipe: %s\n"), command_line); | 127 | |
128 | return STATE_UNKNOWN; | 128 | if (config.check_source) { |
129 | } | 129 | xasprintf(&option_string, "%s--check-source ", option_string); |
130 | 130 | } | |
131 | child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); | 131 | |
132 | if (child_stderr == NULL) { | 132 | char *command_line = NULL; |
133 | printf (_("Could not open stderr for %s\n"), command_line); | 133 | |
134 | } | 134 | if (config.icmp_timestamp) { |
135 | 135 | // no packet size settable for ICMP timestamp | |
136 | while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { | 136 | xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count, server); |
137 | if (verbose) | 137 | } else { |
138 | printf ("%s", input_buffer); | 138 | xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server); |
139 | status = max_state (status, textscan (input_buffer)); | 139 | } |
140 | } | 140 | |
141 | 141 | if (verbose) { | |
142 | /* If we get anything on STDERR, at least set warning */ | 142 | printf("%s\n", command_line); |
143 | while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { | 143 | } |
144 | status = max_state (status, STATE_WARNING); | 144 | |
145 | if (verbose) | 145 | /* run the command */ |
146 | printf ("%s", input_buffer); | 146 | child_process = spopen(command_line); |
147 | status = max_state (status, textscan (input_buffer)); | 147 | if (child_process == NULL) { |
148 | } | 148 | printf(_("Could not open pipe: %s\n"), command_line); |
149 | (void) fclose (child_stderr); | 149 | return STATE_UNKNOWN; |
150 | 150 | } | |
151 | /* close the pipe */ | 151 | |
152 | result = spclose (child_process); | 152 | child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r"); |
153 | if (result) { | 153 | if (child_stderr == NULL) { |
154 | /* need to use max_state not max */ | 154 | printf(_("Could not open stderr for %s\n"), command_line); |
155 | status = max_state (status, STATE_WARNING); | 155 | } |
156 | } | 156 | |
157 | 157 | char *input_buffer = malloc(MAX_INPUT_BUFFER); | |
158 | if (result > 1 ) { | 158 | mp_state_enum status = STATE_UNKNOWN; |
159 | status = max_state (status, STATE_UNKNOWN); | 159 | while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { |
160 | if (result == 2) { | 160 | if (verbose) { |
161 | die (STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n")); | 161 | printf("%s", input_buffer); |
162 | } | 162 | } |
163 | if (result == 3) { | 163 | status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta, |
164 | die (STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n")); | 164 | config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p)); |
165 | } | 165 | } |
166 | if (result == 4) { | 166 | |
167 | die (STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n")); | 167 | /* If we get anything on STDERR, at least set warning */ |
168 | } | 168 | while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { |
169 | 169 | status = max_state(status, STATE_WARNING); | |
170 | } | 170 | if (verbose) { |
171 | 171 | printf("%s", input_buffer); | |
172 | printf ("FPING %s - %s\n", state_text (status), server_name); | 172 | } |
173 | 173 | status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta, | |
174 | return status; | 174 | config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p)); |
175 | } | ||
176 | (void)fclose(child_stderr); | ||
177 | |||
178 | /* close the pipe */ | ||
179 | int result = spclose(child_process); | ||
180 | if (result) { | ||
181 | /* need to use max_state not max */ | ||
182 | status = max_state(status, STATE_WARNING); | ||
183 | } | ||
184 | |||
185 | if (result > 1) { | ||
186 | status = max_state(status, STATE_UNKNOWN); | ||
187 | if (result == 2) { | ||
188 | die(STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n")); | ||
189 | } | ||
190 | if (result == 3) { | ||
191 | die(STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n")); | ||
192 | } | ||
193 | if (result == 4) { | ||
194 | die(STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n")); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | printf("FPING %s - %s\n", state_text(status), config.server_name); | ||
199 | |||
200 | return status; | ||
175 | } | 201 | } |
176 | 202 | ||
177 | 203 | mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p, double wrta, bool cpl_p, int cpl, | |
178 | int textscan (char *buf) { | 204 | bool wpl_p, int wpl, bool alive_p) { |
179 | char *rtastr = NULL; | 205 | /* stops testing after the first successful reply. */ |
180 | char *losstr = NULL; | 206 | double rta; |
181 | char *xmtstr = NULL; | 207 | double loss; |
182 | double loss; | 208 | char *rtastr = NULL; |
183 | double rta; | 209 | if (alive_p && strstr(buf, "avg, 0% loss)")) { |
184 | double xmt; | 210 | rtastr = strstr(buf, "ms ("); |
185 | int status = STATE_UNKNOWN; | 211 | rtastr = 1 + index(rtastr, '('); |
186 | 212 | rta = strtod(rtastr, NULL); | |
187 | /* stops testing after the first successful reply. */ | 213 | loss = strtod("0", NULL); |
188 | if (alive_p && strstr(buf, "avg, 0% loss)")) { | 214 | die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta, |
189 | rtastr = strstr (buf, "ms ("); | 215 | /* No loss since we only waited for the first reply |
190 | rtastr = 1 + index(rtastr, '('); | 216 | perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ |
191 | rta = strtod(rtastr, NULL); | 217 | fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); |
192 | loss=strtod("0",NULL); | 218 | } |
193 | die (STATE_OK, | 219 | |
194 | _("FPING %s - %s (rta=%f ms)|%s\n"), | 220 | mp_state_enum status = STATE_UNKNOWN; |
195 | state_text (STATE_OK), server_name,rta, | 221 | char *xmtstr = NULL; |
196 | /* No loss since we only waited for the first reply | 222 | double xmt; |
197 | perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ | 223 | char *losstr = NULL; |
198 | fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); | 224 | if (strstr(buf, "not found")) { |
199 | } | 225 | die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); |
200 | 226 | ||
201 | if (strstr (buf, "not found")) { | 227 | } else if (strstr(buf, "is unreachable") || strstr(buf, "Unreachable")) { |
202 | die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); | 228 | die(STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), "host"); |
203 | 229 | ||
204 | } | 230 | } else if (strstr(buf, "Operation not permitted") || strstr(buf, "No such device")) { |
205 | else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) { | 231 | die(STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), "host"); |
206 | die (STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), | 232 | } else if (strstr(buf, "is down")) { |
207 | "host"); | 233 | die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); |
208 | 234 | ||
209 | } | 235 | } else if (strstr(buf, "is alive")) { |
210 | else if (strstr (buf, "Operation not permitted") || strstr (buf, "No such device") ) { | 236 | status = STATE_OK; |
211 | die (STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), | 237 | |
212 | "host"); | 238 | } else if (strstr(buf, "xmt/rcv/%loss") && strstr(buf, "min/avg/max")) { |
213 | } | 239 | losstr = strstr(buf, "="); |
214 | else if (strstr (buf, "is down")) { | 240 | losstr = 1 + strstr(losstr, "/"); |
215 | die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); | 241 | losstr = 1 + strstr(losstr, "/"); |
216 | 242 | rtastr = strstr(buf, "min/avg/max"); | |
217 | } | 243 | rtastr = strstr(rtastr, "="); |
218 | else if (strstr (buf, "is alive")) { | 244 | rtastr = 1 + index(rtastr, '/'); |
219 | status = STATE_OK; | 245 | loss = strtod(losstr, NULL); |
220 | 246 | rta = strtod(rtastr, NULL); | |
221 | } | 247 | if (cpl_p && loss > cpl) { |
222 | else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) { | 248 | status = STATE_CRITICAL; |
223 | losstr = strstr (buf, "="); | 249 | } else if (crta_p && rta > crta) { |
224 | losstr = 1 + strstr (losstr, "/"); | 250 | status = STATE_CRITICAL; |
225 | losstr = 1 + strstr (losstr, "/"); | 251 | } else if (wpl_p && loss > wpl) { |
226 | rtastr = strstr (buf, "min/avg/max"); | 252 | status = STATE_WARNING; |
227 | rtastr = strstr (rtastr, "="); | 253 | } else if (wrta_p && rta > wrta) { |
228 | rtastr = 1 + index (rtastr, '/'); | 254 | status = STATE_WARNING; |
229 | loss = strtod (losstr, NULL); | 255 | } else { |
230 | rta = strtod (rtastr, NULL); | 256 | status = STATE_OK; |
231 | if (cpl_p && loss > cpl) | 257 | } |
232 | status = STATE_CRITICAL; | 258 | die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta, |
233 | else if (crta_p && rta > crta) | 259 | perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0), |
234 | status = STATE_CRITICAL; | 260 | fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); |
235 | else if (wpl_p && loss > wpl) | 261 | |
236 | status = STATE_WARNING; | 262 | } else if (strstr(buf, "xmt/rcv/%loss")) { |
237 | else if (wrta_p && rta > wrta) | 263 | /* no min/max/avg if host was unreachable in fping v2.2.b1 */ |
238 | status = STATE_WARNING; | 264 | /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */ |
239 | else | 265 | losstr = strstr(buf, "="); |
240 | status = STATE_OK; | 266 | xmtstr = 1 + losstr; |
241 | die (status, | 267 | xmt = strtod(xmtstr, NULL); |
242 | _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), | 268 | if (xmt == 0) { |
243 | state_text (status), server_name, loss, rta, | 269 | die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); |
244 | perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), | 270 | } |
245 | fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); | 271 | losstr = 1 + strstr(losstr, "/"); |
246 | 272 | losstr = 1 + strstr(losstr, "/"); | |
247 | } | 273 | loss = strtod(losstr, NULL); |
248 | else if(strstr (buf, "xmt/rcv/%loss") ) { | 274 | if (atoi(losstr) == 100) { |
249 | /* no min/max/avg if host was unreachable in fping v2.2.b1 */ | 275 | status = STATE_CRITICAL; |
250 | /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */ | 276 | } else if (cpl_p && loss > cpl) { |
251 | losstr = strstr (buf, "="); | 277 | status = STATE_CRITICAL; |
252 | xmtstr = 1 + losstr; | 278 | } else if (wpl_p && loss > wpl) { |
253 | xmt = strtod (xmtstr, NULL); | 279 | status = STATE_WARNING; |
254 | if(xmt == 0) | 280 | } else { |
255 | die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); | 281 | status = STATE_OK; |
256 | losstr = 1 + strstr (losstr, "/"); | 282 | } |
257 | losstr = 1 + strstr (losstr, "/"); | 283 | /* loss=%.0f%%;%d;%d;0;100 */ |
258 | loss = strtod (losstr, NULL); | 284 | die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss, |
259 | if (atoi(losstr) == 100) | 285 | perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0)); |
260 | status = STATE_CRITICAL; | 286 | |
261 | else if (cpl_p && loss > cpl) | 287 | } else { |
262 | status = STATE_CRITICAL; | 288 | status = max_state(status, STATE_WARNING); |
263 | else if (wpl_p && loss > wpl) | 289 | } |
264 | status = STATE_WARNING; | 290 | |
265 | else | 291 | return status; |
266 | status = STATE_OK; | ||
267 | /* loss=%.0f%%;%d;%d;0;100 */ | ||
268 | die (status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), | ||
269 | state_text (status), server_name, loss , | ||
270 | perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100)); | ||
271 | |||
272 | } | ||
273 | else { | ||
274 | status = max_state (status, STATE_WARNING); | ||
275 | } | ||
276 | |||
277 | return status; | ||
278 | } | 292 | } |
279 | 293 | ||
280 | |||
281 | |||
282 | /* process command-line arguments */ | 294 | /* process command-line arguments */ |
283 | int | 295 | check_fping_config_wrapper process_arguments(int argc, char **argv) { |
284 | process_arguments (int argc, char **argv) | 296 | enum { |
285 | { | 297 | FWMARK_OPT = CHAR_MAX + 1, |
286 | int c; | 298 | ICMP_TIMESTAMP_OPT, |
287 | char *rv[2]; | 299 | CHECK_SOURCE_OPT, |
288 | 300 | }; | |
289 | int option = 0; | 301 | static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, |
290 | static struct option longopts[] = { | 302 | {"sourceip", required_argument, 0, 'S'}, |
291 | {"hostname", required_argument, 0, 'H'}, | 303 | {"sourceif", required_argument, 0, 'I'}, |
292 | {"sourceip", required_argument, 0, 'S'}, | 304 | {"critical", required_argument, 0, 'c'}, |
293 | {"sourceif", required_argument, 0, 'I'}, | 305 | {"warning", required_argument, 0, 'w'}, |
294 | {"critical", required_argument, 0, 'c'}, | 306 | {"alive", no_argument, 0, 'a'}, |
295 | {"warning", required_argument, 0, 'w'}, | 307 | {"bytes", required_argument, 0, 'b'}, |
296 | {"alive", no_argument, 0, 'a'}, | 308 | {"number", required_argument, 0, 'n'}, |
297 | {"bytes", required_argument, 0, 'b'}, | 309 | {"target-timeout", required_argument, 0, 'T'}, |
298 | {"number", required_argument, 0, 'n'}, | 310 | {"interval", required_argument, 0, 'i'}, |
299 | {"target-timeout", required_argument, 0, 'T'}, | 311 | {"verbose", no_argument, 0, 'v'}, |
300 | {"interval", required_argument, 0, 'i'}, | 312 | {"version", no_argument, 0, 'V'}, |
301 | {"verbose", no_argument, 0, 'v'}, | 313 | {"help", no_argument, 0, 'h'}, |
302 | {"version", no_argument, 0, 'V'}, | 314 | {"use-ipv4", no_argument, 0, '4'}, |
303 | {"help", no_argument, 0, 'h'}, | 315 | {"use-ipv6", no_argument, 0, '6'}, |
304 | {"use-ipv4", no_argument, 0, '4'}, | 316 | {"dontfrag", no_argument, 0, 'M'}, |
305 | {"use-ipv6", no_argument, 0, '6'}, | 317 | {"random", no_argument, 0, 'R'}, |
306 | {0, 0, 0, 0} | 318 | #ifdef FPING_VERSION_5_2_OR_HIGHER |
307 | }; | 319 | // only available with fping version >= 5.2 |
308 | 320 | {"fwmark", required_argument, NULL, FWMARK_OPT}, | |
309 | rv[PL] = NULL; | 321 | # ifdef FPING_VERSION_5_3_OR_HIGHER |
310 | rv[RTA] = NULL; | 322 | // only available with fping version >= 5.3 |
311 | 323 | {"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT}, | |
312 | if (argc < 2) | 324 | {"check-source", no_argument, NULL, CHECK_SOURCE_OPT}, |
313 | return ERROR; | 325 | # endif |
314 | |||
315 | if (!is_option (argv[1])) { | ||
316 | server_name = argv[1]; | ||
317 | argv[1] = argv[0]; | ||
318 | argv = &argv[1]; | ||
319 | argc--; | ||
320 | } | ||
321 | |||
322 | while (1) { | ||
323 | c = getopt_long (argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option); | ||
324 | |||
325 | if (c == -1 || c == EOF || c == 1) | ||
326 | break; | ||
327 | |||
328 | switch (c) { | ||
329 | case '?': /* print short usage statement if args not parsable */ | ||
330 | usage5 (); | ||
331 | case 'a': /* host alive mode */ | ||
332 | alive_p = true; | ||
333 | break; | ||
334 | case 'h': /* help */ | ||
335 | print_help (); | ||
336 | exit (STATE_UNKNOWN); | ||
337 | case 'V': /* version */ | ||
338 | print_revision (progname, NP_VERSION); | ||
339 | exit (STATE_UNKNOWN); | ||
340 | case 'v': /* verbose mode */ | ||
341 | verbose = true; | ||
342 | break; | ||
343 | case 'H': /* hostname */ | ||
344 | if (is_host (optarg) == false) { | ||
345 | usage2 (_("Invalid hostname/address"), optarg); | ||
346 | } | ||
347 | server_name = strscpy (server_name, optarg); | ||
348 | break; | ||
349 | case 'S': /* sourceip */ | ||
350 | if (is_host (optarg) == false) { | ||
351 | usage2 (_("Invalid hostname/address"), optarg); | ||
352 | } | ||
353 | sourceip = strscpy (sourceip, optarg); | ||
354 | break; | ||
355 | case 'I': /* sourceip */ | ||
356 | sourceif = strscpy (sourceif, optarg); | ||
357 | break; | ||
358 | case '4': /* IPv4 only */ | ||
359 | address_family = AF_INET; | ||
360 | break; | ||
361 | case '6': /* IPv6 only */ | ||
362 | #ifdef USE_IPV6 | ||
363 | address_family = AF_INET6; | ||
364 | #else | ||
365 | usage (_("IPv6 support not available\n")); | ||
366 | #endif | 326 | #endif |
367 | break; | 327 | {0, 0, 0, 0}}; |
368 | case 'c': | ||
369 | get_threshold (optarg, rv); | ||
370 | if (rv[RTA]) { | ||
371 | crta = strtod (rv[RTA], NULL); | ||
372 | crta_p = true; | ||
373 | rv[RTA] = NULL; | ||
374 | } | ||
375 | if (rv[PL]) { | ||
376 | cpl = atoi (rv[PL]); | ||
377 | cpl_p = true; | ||
378 | rv[PL] = NULL; | ||
379 | } | ||
380 | break; | ||
381 | case 'w': | ||
382 | get_threshold (optarg, rv); | ||
383 | if (rv[RTA]) { | ||
384 | wrta = strtod (rv[RTA], NULL); | ||
385 | wrta_p = true; | ||
386 | rv[RTA] = NULL; | ||
387 | } | ||
388 | if (rv[PL]) { | ||
389 | wpl = atoi (rv[PL]); | ||
390 | wpl_p = true; | ||
391 | rv[PL] = NULL; | ||
392 | } | ||
393 | break; | ||
394 | case 'b': /* bytes per packet */ | ||
395 | if (is_intpos (optarg)) | ||
396 | packet_size = atoi (optarg); | ||
397 | else | ||
398 | usage (_("Packet size must be a positive integer")); | ||
399 | break; | ||
400 | case 'n': /* number of packets */ | ||
401 | if (is_intpos (optarg)) | ||
402 | packet_count = atoi (optarg); | ||
403 | else | ||
404 | usage (_("Packet count must be a positive integer")); | ||
405 | break; | ||
406 | case 'T': /* timeout in msec */ | ||
407 | if (is_intpos (optarg)) | ||
408 | target_timeout = atoi (optarg); | ||
409 | else | ||
410 | usage (_("Target timeout must be a positive integer")); | ||
411 | break; | ||
412 | case 'i': /* interval in msec */ | ||
413 | if (is_intpos (optarg)) | ||
414 | packet_interval = atoi (optarg); | ||
415 | else | ||
416 | usage (_("Interval must be a positive integer")); | ||
417 | break; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | if (server_name == NULL) | ||
422 | usage4 (_("Hostname was not supplied")); | ||
423 | |||
424 | return OK; | ||
425 | } | ||
426 | |||
427 | 328 | ||
428 | int | 329 | char *rv[2]; |
429 | get_threshold (char *arg, char *rv[2]) | 330 | rv[PL] = NULL; |
430 | { | 331 | rv[RTA] = NULL; |
431 | char *arg1 = NULL; | ||
432 | char *arg2 = NULL; | ||
433 | |||
434 | arg1 = strscpy (arg1, arg); | ||
435 | if (strpbrk (arg1, ",:")) | ||
436 | arg2 = 1 + strpbrk (arg1, ",:"); | ||
437 | |||
438 | if (arg2) { | ||
439 | arg1[strcspn (arg1, ",:")] = 0; | ||
440 | if (strstr (arg1, "%") && strstr (arg2, "%")) | ||
441 | die (STATE_UNKNOWN, | ||
442 | _("%s: Only one threshold may be packet loss (%s)\n"), progname, | ||
443 | arg); | ||
444 | if (!strstr (arg1, "%") && !strstr (arg2, "%")) | ||
445 | die (STATE_UNKNOWN, | ||
446 | _("%s: Only one threshold must be packet loss (%s)\n"), | ||
447 | progname, arg); | ||
448 | } | ||
449 | |||
450 | if (arg2 && strstr (arg2, "%")) { | ||
451 | rv[PL] = arg2; | ||
452 | rv[RTA] = arg1; | ||
453 | } | ||
454 | else if (arg2) { | ||
455 | rv[PL] = arg1; | ||
456 | rv[RTA] = arg2; | ||
457 | } | ||
458 | else if (strstr (arg1, "%")) { | ||
459 | rv[PL] = arg1; | ||
460 | } | ||
461 | else { | ||
462 | rv[RTA] = arg1; | ||
463 | } | ||
464 | |||
465 | return OK; | ||
466 | } | ||
467 | 332 | ||
333 | int option = 0; | ||
468 | 334 | ||
469 | void print_help (void) { | 335 | check_fping_config_wrapper result = { |
336 | .errorcode = OK, | ||
337 | .config = check_fping_config_init(), | ||
338 | }; | ||
470 | 339 | ||
471 | print_revision (progname, NP_VERSION); | 340 | if (argc < 2) { |
341 | result.errorcode = ERROR; | ||
342 | return result; | ||
343 | } | ||
472 | 344 | ||
473 | printf ("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); | 345 | if (!is_option(argv[1])) { |
474 | printf (COPYRIGHT, copyright, email); | 346 | result.config.server_name = argv[1]; |
347 | argv[1] = argv[0]; | ||
348 | argv = &argv[1]; | ||
349 | argc--; | ||
350 | } | ||
475 | 351 | ||
476 | printf ("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); | 352 | while (true) { |
353 | int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option); | ||
477 | 354 | ||
478 | printf ("%s\n", _("Note that it is necessary to set the suid flag on fping.")); | 355 | if (option_index == -1 || option_index == EOF || option_index == 1) { |
356 | break; | ||
357 | } | ||
479 | 358 | ||
480 | printf ("\n\n"); | 359 | switch (option_index) { |
360 | case '?': /* print short usage statement if args not parsable */ | ||
361 | usage5(); | ||
362 | case 'a': /* host alive mode */ | ||
363 | result.config.alive_p = true; | ||
364 | break; | ||
365 | case 'h': /* help */ | ||
366 | print_help(); | ||
367 | exit(STATE_UNKNOWN); | ||
368 | case 'V': /* version */ | ||
369 | print_revision(progname, NP_VERSION); | ||
370 | exit(STATE_UNKNOWN); | ||
371 | case 'v': /* verbose mode */ | ||
372 | verbose = true; | ||
373 | break; | ||
374 | case 'H': /* hostname */ | ||
375 | if (!is_host(optarg)) { | ||
376 | usage2(_("Invalid hostname/address"), optarg); | ||
377 | } | ||
378 | result.config.server_name = optarg; | ||
379 | break; | ||
380 | case 'S': /* sourceip */ | ||
381 | if (!is_host(optarg)) { | ||
382 | usage2(_("Invalid hostname/address"), optarg); | ||
383 | } | ||
384 | result.config.sourceip = optarg; | ||
385 | break; | ||
386 | case 'I': /* sourceip */ | ||
387 | result.config.sourceif = optarg; | ||
388 | break; | ||
389 | case '4': /* IPv4 only */ | ||
390 | address_family = AF_INET; | ||
391 | break; | ||
392 | case '6': /* IPv6 only */ | ||
393 | address_family = AF_INET6; | ||
394 | break; | ||
395 | case 'c': | ||
396 | get_threshold(optarg, rv); | ||
397 | if (rv[RTA]) { | ||
398 | result.config.crta = strtod(rv[RTA], NULL); | ||
399 | result.config.crta_p = true; | ||
400 | rv[RTA] = NULL; | ||
401 | } | ||
402 | if (rv[PL]) { | ||
403 | result.config.cpl = atoi(rv[PL]); | ||
404 | result.config.cpl_p = true; | ||
405 | rv[PL] = NULL; | ||
406 | } | ||
407 | break; | ||
408 | case 'w': | ||
409 | get_threshold(optarg, rv); | ||
410 | if (rv[RTA]) { | ||
411 | result.config.wrta = strtod(rv[RTA], NULL); | ||
412 | result.config.wrta_p = true; | ||
413 | rv[RTA] = NULL; | ||
414 | } | ||
415 | if (rv[PL]) { | ||
416 | result.config.wpl = atoi(rv[PL]); | ||
417 | result.config.wpl_p = true; | ||
418 | rv[PL] = NULL; | ||
419 | } | ||
420 | break; | ||
421 | case 'b': /* bytes per packet */ | ||
422 | if (is_intpos(optarg)) { | ||
423 | result.config.packet_size = atoi(optarg); | ||
424 | } else { | ||
425 | usage(_("Packet size must be a positive integer")); | ||
426 | } | ||
427 | break; | ||
428 | case 'n': /* number of packets */ | ||
429 | if (is_intpos(optarg)) { | ||
430 | result.config.packet_count = atoi(optarg); | ||
431 | } else { | ||
432 | usage(_("Packet count must be a positive integer")); | ||
433 | } | ||
434 | break; | ||
435 | case 'T': /* timeout in msec */ | ||
436 | if (is_intpos(optarg)) { | ||
437 | result.config.target_timeout = atoi(optarg); | ||
438 | } else { | ||
439 | usage(_("Target timeout must be a positive integer")); | ||
440 | } | ||
441 | break; | ||
442 | case 'i': /* interval in msec */ | ||
443 | if (is_intpos(optarg)) { | ||
444 | result.config.packet_interval = atoi(optarg); | ||
445 | } else { | ||
446 | usage(_("Interval must be a positive integer")); | ||
447 | } | ||
448 | break; | ||
449 | case 'R': | ||
450 | result.config.randomize_packet_data = true; | ||
451 | break; | ||
452 | case 'M': | ||
453 | result.config.dontfrag = true; | ||
454 | break; | ||
455 | case FWMARK_OPT: | ||
456 | if (is_intpos(optarg)) { | ||
457 | result.config.fwmark = (unsigned int)atol(optarg); | ||
458 | result.config.fwmark_set = true; | ||
459 | } else { | ||
460 | usage(_("fwmark must be a positive integer")); | ||
461 | } | ||
462 | break; | ||
463 | case ICMP_TIMESTAMP_OPT: | ||
464 | result.config.icmp_timestamp = true; | ||
465 | break; | ||
466 | case CHECK_SOURCE_OPT: | ||
467 | result.config.check_source = true; | ||
468 | break; | ||
469 | } | ||
470 | } | ||
481 | 471 | ||
482 | print_usage (); | 472 | if (result.config.server_name == NULL) { |
473 | usage4(_("Hostname was not supplied")); | ||
474 | } | ||
483 | 475 | ||
484 | printf (UT_HELP_VRSN); | 476 | return result; |
485 | printf (UT_EXTRA_OPTS); | 477 | } |
486 | 478 | ||
487 | printf (UT_IPv46); | 479 | int get_threshold(char *arg, char *rv[2]) { |
480 | char *arg2 = NULL; | ||
481 | |||
482 | char *arg1 = strdup(arg); | ||
483 | if (strpbrk(arg1, ",:")) { | ||
484 | arg2 = 1 + strpbrk(arg1, ",:"); | ||
485 | } | ||
486 | |||
487 | if (arg2) { | ||
488 | arg1[strcspn(arg1, ",:")] = 0; | ||
489 | if (strstr(arg1, "%") && strstr(arg2, "%")) { | ||
490 | die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg); | ||
491 | } | ||
492 | if (!strstr(arg1, "%") && !strstr(arg2, "%")) { | ||
493 | die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg); | ||
494 | } | ||
495 | } | ||
496 | |||
497 | if (arg2 && strstr(arg2, "%")) { | ||
498 | rv[PL] = arg2; | ||
499 | rv[RTA] = arg1; | ||
500 | } else if (arg2) { | ||
501 | rv[PL] = arg1; | ||
502 | rv[RTA] = arg2; | ||
503 | } else if (strstr(arg1, "%")) { | ||
504 | rv[PL] = arg1; | ||
505 | } else { | ||
506 | rv[RTA] = arg1; | ||
507 | } | ||
508 | |||
509 | return OK; | ||
510 | } | ||
488 | 511 | ||
489 | printf (" %s\n", "-H, --hostname=HOST"); | 512 | void print_help(void) { |
490 | printf (" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); | 513 | |
491 | printf (" %s\n", "-w, --warning=THRESHOLD"); | 514 | print_revision(progname, NP_VERSION); |
492 | printf (" %s\n", _("warning threshold pair")); | 515 | |
493 | printf (" %s\n", "-c, --critical=THRESHOLD"); | 516 | printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); |
494 | printf (" %s\n", _("critical threshold pair")); | 517 | printf(COPYRIGHT, copyright, email); |
495 | printf (" %s\n", "-a, --alive"); | 518 | |
496 | printf (" %s\n", _("Return OK after first successful reply")); | 519 | printf("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); |
497 | printf (" %s\n", "-b, --bytes=INTEGER"); | 520 | |
498 | printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE); | 521 | printf("%s\n", _("Note that it is necessary to set the suid flag on fping.")); |
499 | printf (" %s\n", "-n, --number=INTEGER"); | 522 | |
500 | printf (" %s (default: %d)\n", _("number of ICMP packets to send"),PACKET_COUNT); | 523 | printf("\n\n"); |
501 | printf (" %s\n", "-T, --target-timeout=INTEGER"); | 524 | |
502 | printf (" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); | 525 | print_usage(); |
503 | printf (" %s\n", "-i, --interval=INTEGER"); | 526 | |
504 | printf (" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); | 527 | printf(UT_HELP_VRSN); |
505 | printf (" %s\n", "-S, --sourceip=HOST"); | 528 | printf(UT_EXTRA_OPTS); |
506 | printf (" %s\n", _("name or IP Address of sourceip")); | 529 | |
507 | printf (" %s\n", "-I, --sourceif=IF"); | 530 | printf(UT_IPv46); |
508 | printf (" %s\n", _("source interface name")); | 531 | |
509 | printf (UT_VERBOSE); | 532 | printf(" %s\n", "-H, --hostname=HOST"); |
510 | printf ("\n"); | 533 | printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); |
511 | printf (" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); | 534 | printf(" %s\n", "-w, --warning=THRESHOLD"); |
512 | printf (" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of")); | 535 | printf(" %s\n", _("warning threshold pair")); |
513 | printf (" %s\n", _("packet loss to trigger an alarm state.")); | 536 | printf(" %s\n", "-c, --critical=THRESHOLD"); |
537 | printf(" %s\n", _("critical threshold pair")); | ||
538 | printf(" %s\n", "-a, --alive"); | ||
539 | printf(" %s\n", _("Return OK after first successful reply")); | ||
540 | printf(" %s\n", "-b, --bytes=INTEGER"); | ||
541 | printf(" %s (default: %d)\n", _("size of ICMP packet"), PACKET_SIZE); | ||
542 | printf(" %s\n", "-n, --number=INTEGER"); | ||
543 | printf(" %s (default: %d)\n", _("number of ICMP packets to send"), PACKET_COUNT); | ||
544 | printf(" %s\n", "-T, --target-timeout=INTEGER"); | ||
545 | printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); | ||
546 | printf(" %s\n", "-i, --interval=INTEGER"); | ||
547 | printf(" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); | ||
548 | printf(" %s\n", "-S, --sourceip=HOST"); | ||
549 | printf(" %s\n", _("name or IP Address of sourceip")); | ||
550 | printf(" %s\n", "-I, --sourceif=IF"); | ||
551 | printf(" %s\n", _("source interface name")); | ||
552 | printf(" %s\n", "-M, --dontfrag"); | ||
553 | printf(" %s\n", _("set the Don't Fragment flag")); | ||
554 | printf(" %s\n", "-R, --random"); | ||
555 | printf(" %s\n", _("random packet data (to foil link data compression)")); | ||
556 | #ifdef FPING_VERSION_5_2_OR_HIGHER | ||
557 | printf(" %s\n", "--fwmark=INTEGER"); | ||
558 | printf(" %s\n", _("set the routing mark to INTEGER (fping option)")); | ||
559 | # ifdef FPING_VERSION_5_3_OR_HIGHER | ||
560 | printf(" %s\n", "--icmp-timestamp"); | ||
561 | printf(" %s\n", _("use ICMP Timestamp instead of ICMP Echo (fping option)")); | ||
562 | printf(" %s\n", "--check-source"); | ||
563 | printf(" %s\n", _("discard replies not from target address (fping option)")); | ||
564 | # endif | ||
565 | #endif | ||
566 | printf(UT_VERBOSE); | ||
567 | printf("\n"); | ||
568 | printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); | ||
569 | printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of")); | ||
570 | printf(" %s\n", _("packet loss to trigger an alarm state.")); | ||
514 | 571 | ||
515 | printf ("\n"); | 572 | printf("\n"); |
516 | printf (" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6.")); | 573 | printf(" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6.")); |
517 | 574 | ||
518 | printf (UT_SUPPORT); | 575 | printf(UT_SUPPORT); |
519 | } | 576 | } |
520 | 577 | ||
521 | 578 | void print_usage(void) { | |
522 | void | 579 | printf("%s\n", _("Usage:")); |
523 | print_usage (void) | 580 | printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname); |
524 | { | ||
525 | printf ("%s\n", _("Usage:")); | ||
526 | printf (" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname); | ||
527 | } | 581 | } |