1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22#include "server_setup.h"
23
24#ifdef HAVE_SIGNAL_H
25#include <signal.h>
26#endif
27#ifdef HAVE_NETINET_IN_H
28#include <netinet/in.h>
29#endif
30#ifdef _XOPEN_SOURCE_EXTENDED
31/* This define is "almost" required to build on HPUX 11 */
32#include <arpa/inet.h>
33#endif
34#ifdef HAVE_NETDB_H
35#include <netdb.h>
36#endif
37#ifdef HAVE_POLL_H
38#include <poll.h>
39#elif defined(HAVE_SYS_POLL_H)
40#include <sys/poll.h>
41#endif
42#ifdef __MINGW32__
43#include <w32api.h>
44#endif
45
46#define ENABLE_CURLX_PRINTF
47/* make the curlx header define all printf() functions to use the curlx_*
48 versions instead */
49#include "curlx.h" /* from the private lib dir */
50#include "getpart.h"
51#include "util.h"
52#include "timeval.h"
53
54#ifdef USE_WINSOCK
55#undef EINTR
56#define EINTR 4 /* errno.h value */
57#undef EINVAL
58#define EINVAL 22 /* errno.h value */
59#endif
60
61/* MinGW with w32api version < 3.6 declared in6addr_any as extern,
62 but lacked the definition */
63#if defined(ENABLE_IPV6) && defined(__MINGW32__)
64#if (__W32API_MAJOR_VERSION < 3) || \
65 ((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 6))
66const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
67#endif /* w32api < 3.6 */
68#endif /* ENABLE_IPV6 && __MINGW32__*/
69
70static struct timeval tvnow(void);
71
72/* This function returns a pointer to STATIC memory. It converts the given
73 * binary lump to a hex formatted string usable for output in logs or
74 * whatever.
75 */
76char *data_to_hex(char *data, size_t len)
77{
78 static char buf[256*3];
79 size_t i;
80 char *optr = buf;
81 char *iptr = data;
82
83 if(len > 255)
84 len = 255;
85
86 for(i = 0; i < len; i++) {
87 if((data[i] >= 0x20) && (data[i] < 0x7f))
88 *optr++ = *iptr++;
89 else {
90 msnprintf(optr, 4, "%%%02x", *iptr++);
91 optr += 3;
92 }
93 }
94 *optr = 0; /* in case no sprintf was used */
95
96 return buf;
97}
98
99void logmsg(const char *msg, ...)
100{
101 va_list ap;
102 char buffer[2048 + 1];
103 FILE *logfp;
104 struct timeval tv;
105 time_t sec;
106 struct tm *now;
107 char timebuf[20];
108 static time_t epoch_offset;
109 static int known_offset;
110
111 if(!serverlogfile) {
112 fprintf(stderr, "Error: serverlogfile not set\n");
113 return;
114 }
115
116 tv = tvnow();
117 if(!known_offset) {
118 epoch_offset = time(NULL) - tv.tv_sec;
119 known_offset = 1;
120 }
121 sec = epoch_offset + tv.tv_sec;
122 now = localtime(&sec); /* not thread safe but we don't care */
123
124 msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld",
125 (int)now->tm_hour, (int)now->tm_min, (int)now->tm_sec,
126 (long)tv.tv_usec);
127
128 va_start(ap, msg);
129 mvsnprintf(buffer, sizeof(buffer), msg, ap);
130 va_end(ap);
131
132 logfp = fopen(serverlogfile, "ab");
133 if(logfp) {
134 fprintf(logfp, "%s %s\n", timebuf, buffer);
135 fclose(logfp);
136 }
137 else {
138 int error = errno;
139 fprintf(stderr, "fopen() failed with error: %d %s\n",
140 error, strerror(error));
141 fprintf(stderr, "Error opening file: %s\n", serverlogfile);
142 fprintf(stderr, "Msg not logged: %s %s\n", timebuf, buffer);
143 }
144}
145
146#ifdef WIN32
147/* use instead of perror() on generic windows */
148void win32_perror(const char *msg)
149{
150 char buf[512];
151 DWORD err = SOCKERRNO;
152
153 if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
154 FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
155 LANG_NEUTRAL, buf, sizeof(buf), NULL))
156 msnprintf(buf, sizeof(buf), "Unknown error %lu (%#lx)", err, err);
157 if(msg)
158 fprintf(stderr, "%s: ", msg);
159 fprintf(stderr, "%s\n", buf);
160}
161#endif /* WIN32 */
162
163#ifdef USE_WINSOCK
164void win32_init(void)
165{
166 WORD wVersionRequested;
167 WSADATA wsaData;
168 int err;
169 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
170
171 err = WSAStartup(wVersionRequested, &wsaData);
172
173 if(err != 0) {
174 perror("Winsock init failed");
175 logmsg("Error initialising winsock -- aborting");
176 exit(1);
177 }
178
179 if(LOBYTE(wsaData.wVersion) != USE_WINSOCK ||
180 HIBYTE(wsaData.wVersion) != USE_WINSOCK) {
181 WSACleanup();
182 perror("Winsock init failed");
183 logmsg("No suitable winsock.dll found -- aborting");
184 exit(1);
185 }
186}
187
188void win32_cleanup(void)
189{
190 WSACleanup();
191}
192#endif /* USE_WINSOCK */
193
194/* set by the main code to point to where the test dir is */
195const char *path = ".";
196
197char *test2file(long testno)
198{
199 static char filename[256];
200 msnprintf(filename, sizeof(filename), TEST_DATA_PATH, path, testno);
201 return filename;
202}
203
204/*
205 * Portable function used for waiting a specific amount of ms.
206 * Waiting indefinitely with this function is not allowed, a
207 * zero or negative timeout value will return immediately.
208 *
209 * Return values:
210 * -1 = system call error, or invalid timeout value
211 * 0 = specified timeout has elapsed
212 */
213int wait_ms(int timeout_ms)
214{
215#if !defined(MSDOS) && !defined(USE_WINSOCK)
216#ifndef HAVE_POLL_FINE
217 struct timeval pending_tv;
218#endif
219 struct timeval initial_tv;
220 int pending_ms;
221#endif
222 int r = 0;
223
224 if(!timeout_ms)
225 return 0;
226 if(timeout_ms < 0) {
227 errno = EINVAL;
228 return -1;
229 }
230#if defined(MSDOS)
231 delay(timeout_ms);
232#elif defined(USE_WINSOCK)
233 Sleep(timeout_ms);
234#else
235 pending_ms = timeout_ms;
236 initial_tv = tvnow();
237 do {
238 int error;
239#if defined(HAVE_POLL_FINE)
240 r = poll(NULL, 0, pending_ms);
241#else
242 pending_tv.tv_sec = pending_ms / 1000;
243 pending_tv.tv_usec = (pending_ms % 1000) * 1000;
244 r = select(0, NULL, NULL, NULL, &pending_tv);
245#endif /* HAVE_POLL_FINE */
246 if(r != -1)
247 break;
248 error = errno;
249 if(error && (error != EINTR))
250 break;
251 pending_ms = timeout_ms - (int)timediff(tvnow(), initial_tv);
252 if(pending_ms <= 0)
253 break;
254 } while(r == -1);
255#endif /* USE_WINSOCK */
256 if(r)
257 r = -1;
258 return r;
259}
260
261int write_pidfile(const char *filename)
262{
263 FILE *pidfile;
264 long pid;
265
266 pid = (long)getpid();
267 pidfile = fopen(filename, "wb");
268 if(!pidfile) {
269 logmsg("Couldn't write pid file: %s %s", filename, strerror(errno));
270 return 0; /* fail */
271 }
272 fprintf(pidfile, "%ld\n", pid);
273 fclose(pidfile);
274 logmsg("Wrote pid %ld to %s", pid, filename);
275 return 1; /* success */
276}
277
278void set_advisor_read_lock(const char *filename)
279{
280 FILE *lockfile;
281 int error = 0;
282 int res;
283
284 do {
285 lockfile = fopen(filename, "wb");
286 } while((lockfile == NULL) && ((error = errno) == EINTR));
287 if(lockfile == NULL) {
288 logmsg("Error creating lock file %s error: %d %s",
289 filename, error, strerror(error));
290 return;
291 }
292
293 do {
294 res = fclose(lockfile);
295 } while(res && ((error = errno) == EINTR));
296 if(res)
297 logmsg("Error closing lock file %s error: %d %s",
298 filename, error, strerror(error));
299}
300
301void clear_advisor_read_lock(const char *filename)
302{
303 int error = 0;
304 int res;
305
306 /*
307 ** Log all removal failures. Even those due to file not existing.
308 ** This allows to detect if unexpectedly the file has already been
309 ** removed by a process different than the one that should do this.
310 */
311
312 do {
313 res = unlink(filename);
314 } while(res && ((error = errno) == EINTR));
315 if(res)
316 logmsg("Error removing lock file %s error: %d %s",
317 filename, error, strerror(error));
318}
319
320
321/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
322 its behavior is altered by the current locale. */
323static char raw_toupper(char in)
324{
325#if !defined(CURL_DOES_CONVERSIONS)
326 if(in >= 'a' && in <= 'z')
327 return (char)('A' + in - 'a');
328#else
329 switch(in) {
330 case 'a':
331 return 'A';
332 case 'b':
333 return 'B';
334 case 'c':
335 return 'C';
336 case 'd':
337 return 'D';
338 case 'e':
339 return 'E';
340 case 'f':
341 return 'F';
342 case 'g':
343 return 'G';
344 case 'h':
345 return 'H';
346 case 'i':
347 return 'I';
348 case 'j':
349 return 'J';
350 case 'k':
351 return 'K';
352 case 'l':
353 return 'L';
354 case 'm':
355 return 'M';
356 case 'n':
357 return 'N';
358 case 'o':
359 return 'O';
360 case 'p':
361 return 'P';
362 case 'q':
363 return 'Q';
364 case 'r':
365 return 'R';
366 case 's':
367 return 'S';
368 case 't':
369 return 'T';
370 case 'u':
371 return 'U';
372 case 'v':
373 return 'V';
374 case 'w':
375 return 'W';
376 case 'x':
377 return 'X';
378 case 'y':
379 return 'Y';
380 case 'z':
381 return 'Z';
382 }
383#endif
384
385 return in;
386}
387
388int strncasecompare(const char *first, const char *second, size_t max)
389{
390 while(*first && *second && max) {
391 if(raw_toupper(*first) != raw_toupper(*second)) {
392 break;
393 }
394 max--;
395 first++;
396 second++;
397 }
398 if(0 == max)
399 return 1; /* they are equal this far */
400
401 return raw_toupper(*first) == raw_toupper(*second);
402}
403
404#if defined(WIN32) && !defined(MSDOS)
405
406static struct timeval tvnow(void)
407{
408 /*
409 ** GetTickCount() is available on _all_ Windows versions from W95 up
410 ** to nowadays. Returns milliseconds elapsed since last system boot,
411 ** increases monotonically and wraps once 49.7 days have elapsed.
412 **
413 ** GetTickCount64() is available on Windows version from Windows Vista
414 ** and Windows Server 2008 up to nowadays. The resolution of the
415 ** function is limited to the resolution of the system timer, which
416 ** is typically in the range of 10 milliseconds to 16 milliseconds.
417 */
418 struct timeval now;
419#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \
420 (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
421 ULONGLONG milliseconds = GetTickCount64();
422#else
423 DWORD milliseconds = GetTickCount();
424#endif
425 now.tv_sec = (long)(milliseconds / 1000);
426 now.tv_usec = (long)((milliseconds % 1000) * 1000);
427 return now;
428}
429
430#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
431
432static struct timeval tvnow(void)
433{
434 /*
435 ** clock_gettime() is granted to be increased monotonically when the
436 ** monotonic clock is queried. Time starting point is unspecified, it
437 ** could be the system start-up time, the Epoch, or something else,
438 ** in any case the time starting point does not change once that the
439 ** system has started up.
440 */
441 struct timeval now;
442 struct timespec tsnow;
443 if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
444 now.tv_sec = tsnow.tv_sec;
445 now.tv_usec = tsnow.tv_nsec / 1000;
446 }
447 /*
448 ** Even when the configure process has truly detected monotonic clock
449 ** availability, it might happen that it is not actually available at
450 ** run-time. When this occurs simply fallback to other time source.
451 */
452#ifdef HAVE_GETTIMEOFDAY
453 else
454 (void)gettimeofday(&now, NULL);
455#else
456 else {
457 now.tv_sec = (long)time(NULL);
458 now.tv_usec = 0;
459 }
460#endif
461 return now;
462}
463
464#elif defined(HAVE_GETTIMEOFDAY)
465
466static struct timeval tvnow(void)
467{
468 /*
469 ** gettimeofday() is not granted to be increased monotonically, due to
470 ** clock drifting and external source time synchronization it can jump
471 ** forward or backward in time.
472 */
473 struct timeval now;
474 (void)gettimeofday(&now, NULL);
475 return now;
476}
477
478#else
479
480static struct timeval tvnow(void)
481{
482 /*
483 ** time() returns the value of time in seconds since the Epoch.
484 */
485 struct timeval now;
486 now.tv_sec = (long)time(NULL);
487 now.tv_usec = 0;
488 return now;
489}
490
491#endif
492
493long timediff(struct timeval newer, struct timeval older)
494{
495 timediff_t diff = newer.tv_sec-older.tv_sec;
496 if(diff >= (LONG_MAX/1000))
497 return LONG_MAX;
498 else if(diff <= (LONG_MIN/1000))
499 return LONG_MIN;
500 return (long)(newer.tv_sec-older.tv_sec)*1000+
501 (long)(newer.tv_usec-older.tv_usec)/1000;
502}
503