summaryrefslogtreecommitdiffstats
path: root/web/attachments/86330-check_http.patch
diff options
context:
space:
mode:
Diffstat (limited to 'web/attachments/86330-check_http.patch')
-rw-r--r--web/attachments/86330-check_http.patch353
1 files changed, 353 insertions, 0 deletions
diff --git a/web/attachments/86330-check_http.patch b/web/attachments/86330-check_http.patch
new file mode 100644
index 0000000..df817d1
--- /dev/null
+++ b/web/attachments/86330-check_http.patch
@@ -0,0 +1,353 @@
1--- /tmp/check_http.c 2004-04-13 20:09:38.000000000 -0700
2+++ check_http.c 2004-04-13 20:25:40.000000000 -0700
3@@ -21,6 +21,8 @@
4 *
5 * $Id: check_http.c,v 1.24.2.4 2003/06/21 05:31:23 kdebisschop Exp $
6 *
7+ * 13-Apr-2004 -- jwz -- added "--no-body" and "--max-age" options
8+ *
9 *****************************************************************************/
10
11 const char *progname = "check_http";
12@@ -45,7 +47,7 @@
13 [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n\
14 [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n\
15 [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n\
16- [-P string]"
17+ [-P string] [-N] [-M <age>]"
18
19 #define LONGOPTIONS "\
20 -H, --hostname=ADDRESS\n\
21@@ -63,6 +65,13 @@
22 Port number (default: %d)\n\
23 -P, --post=STRING\n\
24 URL encoded http POST data\n\
25+ -N, --no-body\n\
26+ Don't wait for document body: stop reading after headers.\n\
27+ (Note that this still does an HTTP GET or POST, not a HEAD.)\n\
28+ -M, --max-age=SECONDS\n\
29+ Warn if the document is more than SECONDS old. The number can\n\
30+ also be of the form \"10m\" for minutes, \"10h\" for hours, or\n\
31+ \"10d\" for days.\n\
32 -w, --warning=INTEGER\n\
33 Response time to result in warning status (seconds)\n\
34 -c, --critical=INTEGER\n\
35@@ -159,6 +168,10 @@
36 int check_certificate (X509 **);
37 #endif
38
39+/* jwz */
40+int no_body = FALSE;
41+int maximum_age = -1;
42+
43 #ifdef HAVE_REGEX_H
44 enum {
45 REGS = 2,
46@@ -311,6 +324,10 @@
47 {"linespan", no_argument, 0, 'l'},
48 {"onredirect", required_argument, 0, 'f'},
49 {"certificate", required_argument, 0, 'C'},
50+
51+ /* jwz */
52+ {"no-body", no_argument, 0, 'N'},
53+ {"max-age", required_argument, 0, 'M'},
54 {0, 0, 0, 0}
55 };
56 #endif
57@@ -331,7 +348,8 @@
58 strcpy (argv[c], "-n");
59 }
60
61-#define OPTCHARS "Vvht:c:w:H:P:I:a:e:p:s:R:r:u:f:C:nlLS"
62+/*#define OPTCHARS "Vvht:c:w:H:P:I:a:e:p:s:R:r:u:f:C:nlLS"*/
63+#define OPTCHARS "Vvht:c:w:H:P:I:a:e:p:s:R:r:u:f:C:M:nlLSN" /* jwz */
64
65 while (1) {
66 #ifdef HAVE_GETOPT_H
67@@ -469,6 +487,27 @@
68 case 'v': /* verbose */
69 verbose = TRUE;
70 break;
71+ case 'N': /* no-body (jwz) */
72+ no_body = TRUE;
73+ break;
74+ case 'M': /* max-age (jwz) */
75+ {
76+ int L = strlen(optarg);
77+ if (L && optarg[L-1] == 'm')
78+ maximum_age = atoi (optarg) * 60;
79+ else if (L && optarg[L-1] == 'h')
80+ maximum_age = atoi (optarg) * 60 * 60;
81+ else if (L && optarg[L-1] == 'd')
82+ maximum_age = atoi (optarg) * 60 * 60 * 24;
83+ else if (L && (optarg[L-1] == 's' ||
84+ isdigit (optarg[L-1])))
85+ maximum_age = atoi (optarg);
86+ else {
87+ fprintf (stderr, "unparsable max-age: %s\n", optarg);
88+ exit (1);
89+ }
90+ }
91+ break;
92 }
93 }
94
95@@ -534,6 +573,223 @@
96
97
98
99+/* Returns 1 if we're done processing the document body; 0 to keep going.
100+ (jwz)
101+ */
102+static int
103+document_headers_done (char *full_page)
104+{
105+ const char *body, *s;
106+ const char *end;
107+
108+ for (body = full_page; *body; body++) {
109+ if (!strncmp (body, "\n\n", 2) ||
110+ !strncmp (body, "\n\r\n", 3))
111+ break;
112+ }
113+
114+ if (!*body)
115+ return 0; /* haven't read end of headers yet */
116+
117+ full_page[body - full_page] = 0;
118+ return 1;
119+}
120+
121+
122+/* jwz */
123+static time_t
124+parse_time_string (const char *string)
125+{
126+ struct tm tm;
127+ time_t t;
128+ memset (&tm, 0, sizeof(tm));
129+
130+ /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
131+
132+ if (isupper (string[0]) && /* Tue */
133+ islower (string[1]) &&
134+ islower (string[2]) &&
135+ ',' == string[3] &&
136+ ' ' == string[4] &&
137+ (isdigit(string[5]) || string[5] == ' ') && /* 25 */
138+ isdigit (string[6]) &&
139+ ' ' == string[7] &&
140+ isupper (string[8]) && /* Dec */
141+ islower (string[9]) &&
142+ islower (string[10]) &&
143+ ' ' == string[11] &&
144+ isdigit (string[12]) && /* 2001 */
145+ isdigit (string[13]) &&
146+ isdigit (string[14]) &&
147+ isdigit (string[15]) &&
148+ ' ' == string[16] &&
149+ isdigit (string[17]) && /* 02: */
150+ isdigit (string[18]) &&
151+ ':' == string[19] &&
152+ isdigit (string[20]) && /* 59: */
153+ isdigit (string[21]) &&
154+ ':' == string[22] &&
155+ isdigit (string[23]) && /* 03 */
156+ isdigit (string[24]) &&
157+ ' ' == string[25] &&
158+ 'G' == string[26] && /* GMT */
159+ 'M' == string[27] && /* GMT */
160+ 'T' == string[28]) {
161+
162+ tm.tm_sec = 10 * (string[23]-'0') + (string[24]-'0');
163+ tm.tm_min = 10 * (string[20]-'0') + (string[21]-'0');
164+ tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
165+ tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
166+ tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
167+ !strncmp (string+8, "Feb", 3) ? 1 :
168+ !strncmp (string+8, "Mar", 3) ? 2 :
169+ !strncmp (string+8, "Apr", 3) ? 3 :
170+ !strncmp (string+8, "May", 3) ? 4 :
171+ !strncmp (string+8, "Jun", 3) ? 5 :
172+ !strncmp (string+8, "Jul", 3) ? 6 :
173+ !strncmp (string+8, "Aug", 3) ? 7 :
174+ !strncmp (string+8, "Sep", 3) ? 8 :
175+ !strncmp (string+8, "Oct", 3) ? 9 :
176+ !strncmp (string+8, "Nov", 3) ? 10 :
177+ !strncmp (string+8, "Dec", 3) ? 11 :
178+ -1);
179+ tm.tm_year = ((1000 * (string[12]-'0') +
180+ 100 * (string[13]-'0') +
181+ 10 * (string[14]-'0') +
182+ (string[15]-'0'))
183+ - 1900);
184+
185+ tm.tm_isdst = 0; /* GMT is never in DST, right? */
186+
187+ if (tm.tm_mon < 0 ||
188+ tm.tm_mday < 1 ||
189+ tm.tm_mday > 31)
190+ return 0;
191+
192+ /* #### This is actually wrong: we need to subtract the local timezone
193+ offset from GMT from this value. But, that's ok in this usage,
194+ because we only comparing these two GMT dates against each other,
195+ so it doesn't matter what time zone we parse them in.
196+ */
197+
198+ t = mktime (&tm);
199+ if (t == (time_t) -1) t = 0;
200+
201+ if (verbose) {
202+ const char *s = string;
203+ while (*s && *s != '\r' && *s != '\n')
204+ fputc (*s++, stdout);
205+ printf (" ==> %lu\n", (unsigned long) t);
206+ }
207+
208+ return t;
209+
210+ } else {
211+ return 0;
212+ }
213+}
214+
215+
216+/* jwz */
217+static void
218+check_document_dates (const char *headers)
219+{
220+ const char *s;
221+ char *server_date = 0;
222+ char *document_date = 0;
223+
224+ s = headers;
225+ while (*s) {
226+ const char *field = s;
227+ const char *value = 0;
228+
229+ /* Find the end of the header field */
230+ while (*s && !isspace(*s) && *s != ':')
231+ s++;
232+
233+ /* Remember the header value, if any. */
234+ if (*s == ':')
235+ value = ++s;
236+
237+ /* Skip to the end of the header, including continuation lines. */
238+ while (*s &&
239+ !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
240+ s++;
241+ s++;
242+
243+ /* Process this header. */
244+ if (value && value > field+2) {
245+ char *ff = (char *) malloc (value-field);
246+ char *ss = ff;
247+ while (field < value-1)
248+ *ss++ = tolower(*field++);
249+ *ss++ = 0;
250+
251+ if (!strcmp (ff, "date") ||
252+ !strcmp (ff, "last-modified")) {
253+ const char *e;
254+ while (*value && isspace (*value))
255+ value++;
256+ for (e = value; *e && *e != '\r' && *e != '\n'; e++)
257+ ;
258+ ss = (char *) malloc (e - value + 1);
259+ strncpy (ss, value, e - value);
260+ ss[e - value] = 0;
261+ if (!strcmp (ff, "date")) {
262+ if (server_date) free (server_date);
263+ server_date = ss;
264+ } else {
265+ if (document_date) free (document_date);
266+ document_date = ss;
267+ }
268+ }
269+ free (ff);
270+ }
271+ }
272+
273+ /* Done parsing the body. Now check the dates we (hopefully) parsed.
274+ */
275+ if (!server_date || !*server_date) {
276+ terminate (STATE_UNKNOWN, "server date unknown\n");
277+ } else if (!document_date || !*document_date) {
278+ terminate (STATE_CRITICAL, "document modification date unknown\n");
279+ } else {
280+ time_t sd = parse_time_string (server_date);
281+ time_t dd = parse_time_string (document_date);
282+ char buf [255];
283+
284+ if (sd <= 0) {
285+ sprintf (buf, "server date \"%100s\" unparsable", server_date);
286+ terminate (STATE_CRITICAL, buf);
287+
288+ } else if (dd <= 0) {
289+ sprintf (buf, "document date \"%100s\" unparsable", document_date);
290+ terminate (STATE_CRITICAL, buf);
291+
292+ } else if (dd > sd + 30) {
293+ char buf[200];
294+ sprintf (buf, "document is %d seconds in the future\n", dd - sd);
295+ terminate (STATE_CRITICAL, buf);
296+
297+ } else if (dd < sd - maximum_age) {
298+ char buf[200];
299+ int n = (sd - dd);
300+ if (n > (60 * 60 * 24 * 2))
301+ sprintf (buf, "last modified %.1f days ago\n",
302+ ((float) n) / (60 * 60 * 24));
303+ else
304+ sprintf (buf, "last modified %d:%02d:%02d ago\n",
305+ n / (60 * 60), (n / 60) % 60, n % 60);
306+ terminate (STATE_CRITICAL, buf);
307+ }
308+
309+ free (server_date);
310+ free (document_date);
311+ }
312+}
313+
314+
315+
316 int
317 check_http (void)
318 {
319@@ -625,6 +881,12 @@
320 buffer[i] = '\0';
321 asprintf (&full_page, "%s%s", full_page, buffer);
322 pagesize += i;
323+
324+ /* jwz */
325+ if (no_body && document_headers_done (full_page)) {
326+ i = 0;
327+ break;
328+ }
329 }
330
331 if (i < 0 && errno != ECONNRESET) {
332@@ -685,7 +947,8 @@
333 page += (size_t) strspn (page, "\r\n");
334 header[pos - header] = 0;
335 if (verbose)
336- printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header, page);
337+ printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
338+ (no_body ? " [[ skipped ]]" : page)); /* jwz */
339
340 /* make sure the status line matches the response we are looking for */
341 if (!strstr (status_line, server_expect)) {
342@@ -810,6 +1073,11 @@
343 } /* end else (server_expect_yn) */
344
345
346+ /* jwz */
347+ if (maximum_age >= 0) {
348+ check_document_dates (header);
349+ }
350+
351 /* check elapsed time */
352 elapsed_time = delta_time (tv);
353 asprintf (&msg, "HTTP problem: %s - %7.3f second response time %s%s|time=%7.3f\n",