Initial import
[olsrd.git] / src / win32 / compat.c
1 /*
2  * Functions for the Windows port
3  * Copyright (C) 2004 Thomas Lopatic (thomas@lopatic.de)
4  *
5  * This file is part of olsrd-unik.
6  *
7  * olsrd-unik is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsrd-unik is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsrd-unik; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 /*
24  * Copyright (c) 1996,1999 by Internet Software Consortium.
25  *
26  * Permission to use, copy, modify, and distribute this software for any
27  * purpose with or without fee is hereby granted, provided that the above
28  * copyright notice and this permission notice appear in all copies.
29  *
30  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
31  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
32  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
33  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
34  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
35  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
36  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37  * SOFTWARE.
38  */
39
40 #include <pthread.h>
41 #include <syslog.h>
42 #include <unistd.h>
43 #include <sys/time.h>
44 #include <ctype.h>
45 #include "defs.h"
46
47 struct ThreadPara
48 {
49   void *(*Func)(void *);
50   void *Arg;
51 };
52
53 static unsigned long __stdcall ThreadWrapper(void *Para)
54 {
55   struct ThreadPara *Cast;
56   void *(*Func)(void *);
57   void *Arg;
58
59   Cast = (struct ThreadPara *)Para;
60
61   Func = Cast->Func;
62   Arg = Cast->Arg;
63   
64   HeapFree(GetProcessHeap(), 0, Para);
65
66   Func(Arg);
67
68   return 0;
69 }
70
71 int pthread_create(HANDLE *Hand, void *Attr, void *(*Func)(void *), void *Arg)
72 {
73   struct ThreadPara *Para;
74   unsigned long ThreadId;
75
76   Para = HeapAlloc(GetProcessHeap(), 0, sizeof (struct ThreadPara));
77
78   if (Para == NULL)
79     return -1;
80
81   Para->Func = Func;
82   Para->Arg = Arg;
83
84   *Hand = CreateThread(NULL, 0, ThreadWrapper, Para, 0, &ThreadId);
85
86   if (*Hand == NULL)
87     return -1;
88
89   return 0;
90 }
91
92 int pthread_kill(HANDLE Hand, int Sig)
93 {
94   if (!TerminateThread(Hand, 0))
95     return -1;
96
97   return 0;
98 }
99
100 int pthread_mutex_init(HANDLE *Hand, void *Attr)
101 {
102   *Hand = CreateMutex(NULL, FALSE, NULL);
103
104   if (*Hand == NULL)
105     return -1;
106
107   return 0;
108 }
109
110 int pthread_mutex_lock(HANDLE *Hand)
111 {
112   if (WaitForSingleObject(*Hand, INFINITE) == WAIT_FAILED)
113     return -1;
114
115   return 0;
116 }
117
118 int pthread_mutex_unlock(HANDLE *Hand)
119 {
120   if (!ReleaseMutex(*Hand))
121     return -1;
122
123   return 0;
124 }
125
126 void syslog(int Pri, char *Form, ...)
127 {
128   Pri = Pri;
129   Form = Form;
130 }
131
132 void openlog(char *Id, int Opt, int Fac)
133 {
134   Id = Id;
135   Opt = Opt;
136   Fac = Fac;
137 }
138
139 void setlogmask(int Mask)
140 {
141   Mask = Mask;
142 }
143
144 void sleep(unsigned int Sec)
145 {
146   Sleep(Sec * 1000);
147 }
148
149 static unsigned int RandState;
150
151 void srandom(unsigned int Seed)
152 {
153   RandState = Seed;
154 }
155
156 unsigned int random(void)
157 {
158   RandState = RandState * 1103515245 + 12345;
159
160   return (RandState ^ (RandState >> 16)) % (RAND_MAX + 1);
161 }
162
163 int getpid(void)
164 {
165   return (int)GetCurrentThread();
166 }
167
168 int nanosleep(struct timespec *Req, struct timespec *Rem)
169 {
170   Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000);
171
172   Rem->tv_sec = 0;
173   Rem->tv_nsec = 0;
174
175   return 0;
176 }
177
178 void gettimeofday(struct timeval *TVal, void *TZone)
179 {
180   SYSTEMTIME SysTime;
181   FILETIME FileTime;
182   unsigned __int64 Ticks;
183
184   GetSystemTime(&SysTime);
185   SystemTimeToFileTime(&SysTime, &FileTime);
186
187   Ticks = ((__int64)FileTime.dwHighDateTime << 32) |
188     (__int64)FileTime.dwLowDateTime;
189
190   Ticks -= 116444736000000000LL;
191
192   TVal->tv_sec = (unsigned int)(Ticks / 10000000);
193   TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
194 }
195
196 int inet_aton(char *AddrStr, struct in_addr *Addr)
197 {
198   Addr->s_addr = inet_addr(AddrStr);
199
200   return 1;
201 }
202
203 char *StrError(unsigned int ErrNo)
204 {
205   static char Msg[1000];
206   
207   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
208                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg,
209                 sizeof (Msg), NULL);
210         
211   return Msg;
212 }
213
214 void PError(char *Str)
215 {
216   char Msg[1000];
217   int Len;
218
219   sprintf(Msg, "ERROR - %s: ", Str);
220
221   Len = strlen(Msg);
222
223   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
224                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg + Len,
225                 sizeof (Msg) - Len, NULL);
226
227   fprintf(stderr, "%s\n", Msg);
228 }
229
230 void WinSockPError(char *Str)
231 {
232   char Msg[1000];
233   int Len;
234
235   sprintf(Msg, "ERROR - %s: ", Str);
236
237   Len = strlen(Msg);
238
239   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(),
240                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg + Len,
241                 sizeof (Msg) - Len, NULL);
242
243   fprintf(stderr, "%s\n", Msg);
244 }
245
246 // XXX - not thread-safe, which is okay for our purposes
247  
248 void *dlopen(char *Name, int Flags)
249 {
250   return (void *)LoadLibrary(Name);
251 }
252
253 int dlclose(void *Handle)
254 {
255   FreeLibrary((HMODULE)Handle);
256   return 0;
257 }
258
259 void *dlsym(void *Handle, char *Name)
260 {
261   return GetProcAddress((HMODULE)Handle, Name);
262 }
263
264 char *dlerror(void)
265 {
266   return StrError(GetLastError());
267 }
268
269 #define NS_INADDRSZ 4
270 #define NS_IN6ADDRSZ 16
271 #define NS_INT16SZ 2
272
273 static int inet_pton4(const char *src, unsigned char *dst)
274 {
275   int saw_digit, octets, ch;
276   u_char tmp[NS_INADDRSZ], *tp;
277
278   saw_digit = 0;
279   octets = 0;
280   *(tp = tmp) = 0;
281
282   while ((ch = *src++) != '\0')
283   {
284     if (ch >= '0' && ch <= '9') {
285       unsigned int new = *tp * 10 + (ch - '0');
286
287       if (new > 255)
288         return (0);
289
290       *tp = new;
291
292       if (!saw_digit)
293       {
294         if (++octets > 4)
295           return (0);
296
297         saw_digit = 1;
298       }
299     }
300
301     else if (ch == '.' && saw_digit)
302     {
303       if (octets == 4)
304         return (0);
305
306       *++tp = 0;
307
308       saw_digit = 0;
309     }
310
311     else
312       return (0);
313   }
314
315   if (octets < 4)
316     return (0);
317
318   memcpy(dst, tmp, NS_INADDRSZ);
319   return (1);
320 }
321
322 static int inet_pton6(const char *src, unsigned char *dst)
323 {
324   static const char xdigits[] = "0123456789abcdef";
325   u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
326   const char *curtok;
327   int ch, saw_xdigit;
328   u_int val;
329
330   tp = memset(tmp, '\0', NS_IN6ADDRSZ);
331   endp = tp + NS_IN6ADDRSZ;
332   colonp = NULL;
333
334   if (*src == ':')
335     if (*++src != ':')
336       return (0);
337
338   curtok = src;
339   saw_xdigit = 0;
340   val = 0;
341
342   while ((ch = tolower (*src++)) != '\0')
343   {
344     const char *pch;
345
346     pch = strchr(xdigits, ch);
347
348     if (pch != NULL)
349     {
350       val <<= 4;
351       val |= (pch - xdigits);
352
353       if (val > 0xffff)
354         return (0);
355
356       saw_xdigit = 1;
357       continue;
358     }
359
360     if (ch == ':')
361     {
362       curtok = src;
363
364       if (!saw_xdigit)
365       {
366         if (colonp)
367           return (0);
368
369         colonp = tp;
370         continue;
371       }
372
373       else if (*src == '\0')
374       {
375         return (0);
376       }
377
378       if (tp + NS_INT16SZ > endp)
379         return (0);
380
381       *tp++ = (u_char) (val >> 8) & 0xff;
382       *tp++ = (u_char) val & 0xff;
383       saw_xdigit = 0;
384       val = 0;
385       continue;
386     }
387
388     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
389         inet_pton4(curtok, tp) > 0)
390     {
391       tp += NS_INADDRSZ;
392       saw_xdigit = 0;
393       break;
394     }
395
396     return (0);
397   }
398
399   if (saw_xdigit)
400   {
401     if (tp + NS_INT16SZ > endp)
402       return (0);
403
404     *tp++ = (u_char) (val >> 8) & 0xff;
405     *tp++ = (u_char) val & 0xff;
406   }
407
408   if (colonp != NULL)
409   {
410     const int n = tp - colonp;
411     int i;
412
413     if (tp == endp)
414       return (0);
415
416     for (i = 1; i <= n; i++)
417     {
418       endp[- i] = colonp[n - i];
419       colonp[n - i] = 0;
420     }
421
422     tp = endp;
423   }
424
425   if (tp != endp)
426     return (0);
427
428   memcpy(dst, tmp, NS_IN6ADDRSZ);
429   return (1);
430 }
431
432 int inet_pton(int af, char *src, void *dst)
433 {
434   switch (af)
435   {
436   case AF_INET:
437     return (inet_pton4(src, dst));
438
439   case AF_INET6:
440     return (inet_pton6(src, dst));
441
442   default:
443     return -1;
444   }
445 }
446
447 static char *inet_ntop4(const unsigned char *src, char *dst, int size)
448 {
449   static const char fmt[] = "%u.%u.%u.%u";
450   char tmp[sizeof "255.255.255.255"];
451
452   if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
453     return (NULL);
454
455   return strcpy(dst, tmp);
456 }
457
458 static char *inet_ntop6(const unsigned char *src, char *dst, int size)
459 {
460   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
461   struct { int base, len; } best, cur;
462   u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
463   int i;
464
465   memset(words, '\0', sizeof words);
466
467   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
468     words[i / 2] = (src[i] << 8) | src[i + 1];
469
470   best.base = -1;
471   cur.base = -1;
472
473   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
474   {
475     if (words[i] == 0)
476     {
477       if (cur.base == -1)
478         cur.base = i, cur.len = 1;
479
480       else
481         cur.len++;
482     }
483
484     else
485     {
486       if (cur.base != -1)
487       {
488         if (best.base == -1 || cur.len > best.len)
489           best = cur;
490
491         cur.base = -1;
492       }
493     }
494   }
495
496   if (cur.base != -1)
497   {
498     if (best.base == -1 || cur.len > best.len)
499       best = cur;
500   }
501
502   if (best.base != -1 && best.len < 2)
503     best.base = -1;
504
505   tp = tmp;
506
507   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
508   {
509     if (best.base != -1 && i >= best.base && i < (best.base + best.len))
510     {
511       if (i == best.base)
512         *tp++ = ':';
513
514       continue;
515     }
516
517     if (i != 0)
518       *tp++ = ':';
519
520     
521     if (i == 6 && best.base == 0 &&
522         (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
523     {
524       if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
525         return (NULL);
526
527       tp += strlen(tp);
528
529       break;
530     }
531
532     tp += sprintf(tp, "%x", words[i]);
533   }
534
535   if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
536     *tp++ = ':';
537
538   *tp++ = '\0';
539
540   if ((tp - tmp) > size)
541     return (NULL);
542
543   return strcpy(dst, tmp);
544 }
545
546 char *inet_ntop(int af, void *src, char *dst, int size)
547 {
548   switch (af)
549   {
550   case AF_INET:
551     return (inet_ntop4(src, dst, size));
552
553   case AF_INET6:
554     return (inet_ntop6(src, dst, size));
555
556   default:
557     return (NULL);
558   }
559 }