2e3ab714f3b2ba264ff7f66449ae0444ced498b6
[olsrd.git] / src / win32 / compat.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
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 <ctype.h>
62 #include <dlfcn.h>
63 #include <io.h>
64 #include <arpa/inet.h>
65
66 #include "defs.h"
67 #include "common/string.h"
68 #include "os_time.h"
69
70 static unsigned int RandState;
71
72 void
73 srandom(unsigned int Seed)
74 {
75   RandState = Seed;
76 }
77
78 unsigned int
79 random(void)
80 {
81   RandState = RandState * 1103515245 + 12345;
82
83   return (RandState ^ (RandState >> 16)) & RAND_MAX;
84 }
85
86 int
87 getpid(void)
88 {
89   HANDLE h = GetCurrentThread();
90   return (int)h;
91 }
92
93 char *
94 win32_strerror(unsigned int ErrNo)
95 {
96   static char Msg[1000];
97
98 #if !defined WINCE
99   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg, sizeof(Msg), NULL);
100 #else
101   short WideMsg[1000];
102
103   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
104                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg, sizeof(WideMsg) / 2, NULL);
105
106   if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof(Msg), NULL, NULL) == 0)
107     strscpy(Msg, "[cannot convert string]", sizeof(Msg));
108 #endif
109
110   return Msg;
111 }
112
113 // XXX - not thread-safe, which is okay for our purposes
114 void *
115 dlopen(const char *Name, int Flags __attribute__ ((unused)))
116 {
117 #if !defined WINCE
118   return (void *)LoadLibrary(Name);
119 #else
120   short WideName[1000];
121
122   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof(WideName));
123   return (void *)LoadLibrary(WideName);
124 #endif
125 }
126
127 int
128 dlclose(void *Handle)
129 {
130   FreeLibrary((HMODULE) Handle);
131   return 0;
132 }
133
134 void *
135 dlsym(void *Handle, const char *Name)
136 {
137 #if !defined WINCE
138   return GetProcAddress((HMODULE) Handle, Name);
139 #else
140   short WideName[1000];
141
142   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof(WideName));
143   return GetProcAddress((HMODULE) Handle, WideName);
144 #endif
145 }
146
147 char *
148 dlerror(void)
149 {
150   return win32_strerror(GetLastError());
151 }
152
153 #define NS_INADDRSZ 4
154 #define NS_IN6ADDRSZ 16
155 #define NS_INT16SZ 2
156
157 static int
158 inet_pton4(const char *src, unsigned char *dst)
159 {
160   int saw_digit, octets, ch;
161   u_char tmp[NS_INADDRSZ], *tp;
162
163   saw_digit = 0;
164   octets = 0;
165   *(tp = tmp) = 0;
166
167   while ((ch = *src++) != '\0') {
168     if (ch >= '0' && ch <= '9') {
169       unsigned int new = *tp * 10 + (ch - '0');
170
171       if (new > 255)
172         return (0);
173
174       *tp = new;
175
176       if (!saw_digit) {
177         if (++octets > 4)
178           return (0);
179
180         saw_digit = 1;
181       }
182     }
183
184     else if (ch == '.' && saw_digit) {
185       if (octets == 4)
186         return (0);
187
188       *++tp = 0;
189
190       saw_digit = 0;
191     }
192
193     else
194       return (0);
195   }
196
197   if (octets < 4)
198     return (0);
199
200   memcpy(dst, tmp, NS_INADDRSZ);
201   return (1);
202 }
203
204 static int
205 inet_pton6(const char *src, unsigned char *dst)
206 {
207   static const char xdigits[] = "0123456789abcdef";
208   u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
209   const char *curtok;
210   int ch, saw_xdigit;
211   u_int val;
212
213   tp = memset(tmp, '\0', NS_IN6ADDRSZ);
214   endp = tp + NS_IN6ADDRSZ;
215   colonp = NULL;
216
217   if (*src == ':')
218     if (*++src != ':')
219       return (0);
220
221   curtok = src;
222   saw_xdigit = 0;
223   val = 0;
224
225   while ((ch = tolower(*src++)) != '\0') {
226     const char *pch;
227
228     pch = strchr(xdigits, ch);
229
230     if (pch != NULL) {
231       val <<= 4;
232       val |= (pch - xdigits);
233
234       if (val > 0xffff)
235         return (0);
236
237       saw_xdigit = 1;
238       continue;
239     }
240
241     if (ch == ':') {
242       curtok = src;
243
244       if (!saw_xdigit) {
245         if (colonp)
246           return (0);
247
248         colonp = tp;
249         continue;
250       }
251
252       else if (*src == '\0') {
253         return (0);
254       }
255
256       if (tp + NS_INT16SZ > endp)
257         return (0);
258
259       *tp++ = (u_char) (val >> 8) & 0xff;
260       *tp++ = (u_char) val & 0xff;
261       saw_xdigit = 0;
262       val = 0;
263       continue;
264     }
265
266     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) {
267       tp += NS_INADDRSZ;
268       saw_xdigit = 0;
269       break;
270     }
271
272     return (0);
273   }
274
275   if (saw_xdigit) {
276     if (tp + NS_INT16SZ > endp)
277       return (0);
278
279     *tp++ = (u_char) (val >> 8) & 0xff;
280     *tp++ = (u_char) val & 0xff;
281   }
282
283   if (colonp != NULL) {
284     const int n = tp - colonp;
285     int i;
286
287     if (tp == endp)
288       return (0);
289
290     for (i = 1; i <= n; i++) {
291       endp[-i] = colonp[n - i];
292       colonp[n - i] = 0;
293     }
294
295     tp = endp;
296   }
297
298   if (tp != endp)
299     return (0);
300
301   memcpy(dst, tmp, NS_IN6ADDRSZ);
302   return (1);
303 }
304
305 int
306 inet_pton(int af, const char *src, void *dst)
307 {
308   switch (af) {
309   case AF_INET:
310     return (inet_pton4(src, dst));
311
312   case AF_INET6:
313     return (inet_pton6(src, dst));
314
315   default:
316     return -1;
317   }
318 }
319
320 static char *
321 inet_ntop4(const unsigned char *src, char *dst, int size)
322 {
323   static const char fmt[] = "%u.%u.%u.%u";
324   char tmp[sizeof "255.255.255.255"];
325
326   if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
327     return (NULL);
328
329   return strscpy(dst, tmp, size);
330 }
331
332 static char *
333 inet_ntop6(const unsigned char *src, char *dst, int size)
334 {
335   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
336   struct {
337     int base, len;
338   } best, cur;
339   u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
340   int i;
341
342   memset(words, '\0', sizeof words);
343
344   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
345     words[i / 2] = (src[i] << 8) | src[i + 1];
346
347   best.base = -1;
348   cur.base = -1;
349
350   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
351     if (words[i] == 0) {
352       if (cur.base == -1)
353         cur.base = i, cur.len = 1;
354
355       else
356         cur.len++;
357     }
358
359     else {
360       if (cur.base != -1) {
361         if (best.base == -1 || cur.len > best.len)
362           best = cur;
363
364         cur.base = -1;
365       }
366     }
367   }
368
369   if (cur.base != -1) {
370     if (best.base == -1 || cur.len > best.len)
371       best = cur;
372   }
373
374   if (best.base != -1 && best.len < 2)
375     best.base = -1;
376
377   tp = tmp;
378
379   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
380     if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
381       if (i == best.base)
382         *tp++ = ':';
383
384       continue;
385     }
386
387     if (i != 0)
388       *tp++ = ':';
389
390
391     if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
392       if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
393         return (NULL);
394
395       tp += strlen(tp);
396
397       break;
398     }
399
400     tp += sprintf(tp, "%x", words[i]);
401   }
402
403   if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
404     *tp++ = ':';
405
406   *tp++ = '\0';
407
408   if ((tp - tmp) > size)
409     return (NULL);
410
411   return strscpy(dst, tmp, size);
412 }
413
414 char *
415 inet_ntop(int af, const void *src, char *dst, int size)
416 {
417   switch (af) {
418   case AF_INET:
419     return (inet_ntop4(src, dst, size));
420
421   case AF_INET6:
422     return (inet_ntop6(src, dst, size));
423
424   default:
425     return (NULL);
426   }
427 }
428
429 int
430 isatty(int fd)
431 {
432 #if !defined WINCE
433   HANDLE Hand;
434   CONSOLE_SCREEN_BUFFER_INFO Info;
435   unsigned long Events;
436
437   if (fd == 0) {
438     Hand = GetStdHandle(STD_INPUT_HANDLE);
439     return GetNumberOfConsoleInputEvents(Hand, &Events);
440   }
441
442   else if (fd == 1) {
443     Hand = GetStdHandle(STD_OUTPUT_HANDLE);
444     return GetConsoleScreenBufferInfo(Hand, &Info);
445   }
446
447   else if (fd == 2) {
448     Hand = GetStdHandle(STD_ERROR_HANDLE);
449     return GetConsoleScreenBufferInfo(Hand, &Info);
450   }
451
452   return -1;
453 #else
454   return 0;
455 #endif
456 }
457
458 #define CHUNK_SIZE 512
459
460 /* and we emulate a real write(2) syscall using send() */
461 int
462 write(int fd, const void *buf, unsigned int count)
463 {
464   size_t written = 0;
465   while (written < count) {
466     ssize_t rc = send(fd, (const void *)((const unsigned char *)buf + written),
467                       min(count - written, CHUNK_SIZE), 0);
468     if (rc <= 0) {
469       break;
470     }
471     written += rc;
472   }
473   return written;
474 }
475
476 /*
477  * Local Variables:
478  * c-basic-offset: 2
479  * indent-tabs-mode: nil
480  * End:
481  */