Fix ipcalc.h for bsd
[olsrd.git] / src / win32 / compat.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon (olsrd)
4  * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 /*
43  * Copyright (c) 1996,1999 by Internet Software Consortium.
44  *
45  * Permission to use, copy, modify, and distribute this software for any
46  * purpose with or without fee is hereby granted, provided that the above
47  * copyright notice and this permission notice appear in all copies.
48  *
49  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
50  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
51  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
52  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
53  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
54  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
55  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56  * SOFTWARE.
57  */
58
59 #include <unistd.h>
60 #include <sys/time.h>
61 #include <sys/times.h>
62 #include <ctype.h>
63 #include <dlfcn.h>
64 #include <io.h>
65 #include <arpa/inet.h>
66
67 #include "defs.h"
68
69 void PError(char *Str);
70 void WinSockPError(char *Str);
71
72 void
73 sleep(unsigned int Sec)
74 {
75   Sleep(Sec * 1000);
76 }
77
78 static unsigned int RandState;
79
80 void
81 srandom(unsigned int Seed)
82 {
83   RandState = Seed;
84 }
85
86 unsigned int
87 random(void)
88 {
89   RandState = RandState * 1103515245 + 12345;
90
91   return (RandState ^ (RandState >> 16)) & RAND_MAX;
92 }
93
94 int
95 getpid(void)
96 {
97   HANDLE h = GetCurrentThread();
98   return (int)h;
99 }
100
101 int
102 nanosleep(struct timespec *Req, struct timespec *Rem)
103 {
104   Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000);
105
106   Rem->tv_sec = 0;
107   Rem->tv_nsec = 0;
108
109   return 0;
110 }
111
112 int
113 gettimeofday(struct timeval *TVal, void *TZone __attribute__ ((unused)))
114 {
115   SYSTEMTIME SysTime;
116   FILETIME FileTime;
117   unsigned __int64 Ticks;
118
119   GetSystemTime(&SysTime);
120   SystemTimeToFileTime(&SysTime, &FileTime);
121
122   Ticks = ((__int64) FileTime.dwHighDateTime << 32) | (__int64) FileTime.dwLowDateTime;
123
124   Ticks -= 116444736000000000LL;
125
126   TVal->tv_sec = (unsigned int)(Ticks / 10000000);
127   TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
128   return 0;
129 }
130
131 long
132 times(struct tms *Dummy __attribute__ ((unused)))
133 {
134   return (long)GetTickCount();
135 }
136
137 int
138 inet_aton(const char *AddrStr, struct in_addr *Addr)
139 {
140   Addr->s_addr = inet_addr(AddrStr);
141
142   return 1;
143 }
144
145 char *
146 StrError(unsigned int ErrNo)
147 {
148   static char Msg[1000];
149
150 #if !defined WINCE
151   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg, sizeof(Msg), NULL);
152 #else
153   short WideMsg[1000];
154
155   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg, sizeof(WideMsg) / 2,
156                 NULL);
157
158   if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof(Msg), NULL, NULL) == 0)
159     strscpy(Msg, "[cannot convert string]", sizeof(Msg));
160 #endif
161
162   return Msg;
163 }
164
165 void
166 PError(char *Str)
167 {
168   fprintf(stderr, "ERROR - %s: %s", Str, StrError(GetLastError()));
169 }
170
171 void
172 WinSockPError(char *Str)
173 {
174   fprintf(stderr, "ERROR - %s: %s", Str, StrError(WSAGetLastError()));
175 }
176
177 // XXX - not thread-safe, which is okay for our purposes
178
179 void *
180 dlopen(char *Name, int Flags __attribute__ ((unused)))
181 {
182 #if !defined WINCE
183   return (void *)LoadLibrary(Name);
184 #else
185   short WideName[1000];
186
187   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof(WideName));
188   return (void *)LoadLibrary(WideName);
189 #endif
190 }
191
192 int
193 dlclose(void *Handle)
194 {
195   FreeLibrary((HMODULE) Handle);
196   return 0;
197 }
198
199 void *
200 dlsym(void *Handle, const char *Name)
201 {
202 #if !defined WINCE
203   return GetProcAddress((HMODULE) Handle, Name);
204 #else
205   short WideName[1000];
206
207   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof(WideName));
208   return GetProcAddress((HMODULE) Handle, WideName);
209 #endif
210 }
211
212 char *
213 dlerror(void)
214 {
215   return StrError(GetLastError());
216 }
217
218 #define NS_INADDRSZ 4
219 #define NS_IN6ADDRSZ 16
220 #define NS_INT16SZ 2
221
222 static int
223 inet_pton4(const char *src, unsigned char *dst)
224 {
225   int saw_digit, octets, ch;
226   u_char tmp[NS_INADDRSZ], *tp;
227
228   saw_digit = 0;
229   octets = 0;
230   *(tp = tmp) = 0;
231
232   while ((ch = *src++) != '\0') {
233     if (ch >= '0' && ch <= '9') {
234       unsigned int new = *tp * 10 + (ch - '0');
235
236       if (new > 255)
237         return (0);
238
239       *tp = new;
240
241       if (!saw_digit) {
242         if (++octets > 4)
243           return (0);
244
245         saw_digit = 1;
246       }
247     }
248
249     else if (ch == '.' && saw_digit) {
250       if (octets == 4)
251         return (0);
252
253       *++tp = 0;
254
255       saw_digit = 0;
256     }
257
258     else
259       return (0);
260   }
261
262   if (octets < 4)
263     return (0);
264
265   memcpy(dst, tmp, NS_INADDRSZ);
266   return (1);
267 }
268
269 static int
270 inet_pton6(const char *src, unsigned char *dst)
271 {
272   static const char xdigits[] = "0123456789abcdef";
273   u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
274   const char *curtok;
275   int ch, saw_xdigit;
276   u_int val;
277
278   tp = memset(tmp, '\0', NS_IN6ADDRSZ);
279   endp = tp + NS_IN6ADDRSZ;
280   colonp = NULL;
281
282   if (*src == ':')
283     if (*++src != ':')
284       return (0);
285
286   curtok = src;
287   saw_xdigit = 0;
288   val = 0;
289
290   while ((ch = tolower(*src++)) != '\0') {
291     const char *pch;
292
293     pch = strchr(xdigits, ch);
294
295     if (pch != NULL) {
296       val <<= 4;
297       val |= (pch - xdigits);
298
299       if (val > 0xffff)
300         return (0);
301
302       saw_xdigit = 1;
303       continue;
304     }
305
306     if (ch == ':') {
307       curtok = src;
308
309       if (!saw_xdigit) {
310         if (colonp)
311           return (0);
312
313         colonp = tp;
314         continue;
315       }
316
317       else if (*src == '\0') {
318         return (0);
319       }
320
321       if (tp + NS_INT16SZ > endp)
322         return (0);
323
324       *tp++ = (u_char) (val >> 8) & 0xff;
325       *tp++ = (u_char) val & 0xff;
326       saw_xdigit = 0;
327       val = 0;
328       continue;
329     }
330
331     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) {
332       tp += NS_INADDRSZ;
333       saw_xdigit = 0;
334       break;
335     }
336
337     return (0);
338   }
339
340   if (saw_xdigit) {
341     if (tp + NS_INT16SZ > endp)
342       return (0);
343
344     *tp++ = (u_char) (val >> 8) & 0xff;
345     *tp++ = (u_char) val & 0xff;
346   }
347
348   if (colonp != NULL) {
349     const int n = tp - colonp;
350     int i;
351
352     if (tp == endp)
353       return (0);
354
355     for (i = 1; i <= n; i++) {
356       endp[-i] = colonp[n - i];
357       colonp[n - i] = 0;
358     }
359
360     tp = endp;
361   }
362
363   if (tp != endp)
364     return (0);
365
366   memcpy(dst, tmp, NS_IN6ADDRSZ);
367   return (1);
368 }
369
370 int
371 inet_pton(int af, const char *src, void *dst)
372 {
373   switch (af) {
374   case AF_INET:
375     return (inet_pton4(src, dst));
376
377   case AF_INET6:
378     return (inet_pton6(src, dst));
379
380   default:
381     return -1;
382   }
383 }
384
385 static char *
386 inet_ntop4(const unsigned char *src, char *dst, int size)
387 {
388   static const char fmt[] = "%u.%u.%u.%u";
389   char tmp[sizeof "255.255.255.255"];
390
391   if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
392     return (NULL);
393
394   return strscpy(dst, tmp, size);
395 }
396
397 static char *
398 inet_ntop6(const unsigned char *src, char *dst, int size)
399 {
400   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
401   struct {
402     int base, len;
403   } best, cur;
404   u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
405   int i;
406
407   memset(words, '\0', sizeof words);
408
409   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
410     words[i / 2] = (src[i] << 8) | src[i + 1];
411
412   best.base = -1;
413   cur.base = -1;
414
415   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
416     if (words[i] == 0) {
417       if (cur.base == -1)
418         cur.base = i, cur.len = 1;
419
420       else
421         cur.len++;
422     }
423
424     else {
425       if (cur.base != -1) {
426         if (best.base == -1 || cur.len > best.len)
427           best = cur;
428
429         cur.base = -1;
430       }
431     }
432   }
433
434   if (cur.base != -1) {
435     if (best.base == -1 || cur.len > best.len)
436       best = cur;
437   }
438
439   if (best.base != -1 && best.len < 2)
440     best.base = -1;
441
442   tp = tmp;
443
444   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
445     if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
446       if (i == best.base)
447         *tp++ = ':';
448
449       continue;
450     }
451
452     if (i != 0)
453       *tp++ = ':';
454
455     if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
456       if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
457         return (NULL);
458
459       tp += strlen(tp);
460
461       break;
462     }
463
464     tp += sprintf(tp, "%x", words[i]);
465   }
466
467   if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
468     *tp++ = ':';
469
470   *tp++ = '\0';
471
472   if ((tp - tmp) > size)
473     return (NULL);
474
475   return strscpy(dst, tmp, size);
476 }
477
478 char *
479 inet_ntop(int af, const void *src, char *dst, int size)
480 {
481   switch (af) {
482   case AF_INET:
483     return (inet_ntop4(src, dst, size));
484
485   case AF_INET6:
486     return (inet_ntop6(src, dst, size));
487
488   default:
489     return (NULL);
490   }
491 }
492
493 int
494 isatty(int fd)
495 {
496 #if !defined WINCE
497   HANDLE Hand;
498   CONSOLE_SCREEN_BUFFER_INFO Info;
499   unsigned long Events;
500
501   if (fd == 0) {
502     Hand = GetStdHandle(STD_INPUT_HANDLE);
503     return GetNumberOfConsoleInputEvents(Hand, &Events);
504   }
505
506   else if (fd == 1) {
507     Hand = GetStdHandle(STD_OUTPUT_HANDLE);
508     return GetConsoleScreenBufferInfo(Hand, &Info);
509   }
510
511   else if (fd == 2) {
512     Hand = GetStdHandle(STD_ERROR_HANDLE);
513     return GetConsoleScreenBufferInfo(Hand, &Info);
514   }
515
516   return -1;
517 #else
518   return 0;
519 #endif
520 }
521
522 #define CHUNK_SIZE 512
523
524 /* and we emulate a real write(2) syscall using send() */
525 int
526 write(int fd, const void *buf, unsigned int count)
527 {
528   size_t written = 0;
529   while (written < count) {
530     ssize_t rc = send(fd, (const unsigned char *)buf + written,
531                       min(count - written, CHUNK_SIZE), 0);
532     if (rc <= 0) {
533       break;
534     }
535     written += rc;
536   }
537   return written;
538 }
539
540 /*
541  * Local Variables:
542  * c-basic-offset: 2
543  * indent-tabs-mode: nil
544  * End:
545  */