/* * The olsr.org Optimized Link-State Routing daemon (olsrd) * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of olsr.org, olsrd nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Visit http://www.olsr.org for more information. * * If you find this software useful feel free to make a donation * to the project. For more information see the website or contact * the copyright holders. * * $Id: compat.c,v 1.16 2007/07/15 21:09:38 bernd67 Exp $ */ /* * Copyright (c) 1996,1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include #include #include #include #include #include #include "defs.h" void PError(char *Str); void WinSockPError(char *Str); void sleep(unsigned int Sec) { Sleep(Sec * 1000); } static unsigned int RandState; void srandom(unsigned int Seed) { RandState = Seed; } unsigned int random(void) { RandState = RandState * 1103515245 + 12345; return (RandState ^ (RandState >> 16)) & RAND_MAX; } int getpid(void) { return (int)GetCurrentThread(); } int nanosleep(struct timespec *Req, struct timespec *Rem) { Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000); Rem->tv_sec = 0; Rem->tv_nsec = 0; return 0; } void gettimeofday(struct timeval *TVal, void *TZone __attribute__((unused))) { SYSTEMTIME SysTime; FILETIME FileTime; unsigned __int64 Ticks; GetSystemTime(&SysTime); SystemTimeToFileTime(&SysTime, &FileTime); Ticks = ((__int64)FileTime.dwHighDateTime << 32) | (__int64)FileTime.dwLowDateTime; Ticks -= 116444736000000000LL; TVal->tv_sec = (unsigned int)(Ticks / 10000000); TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10; } long times(struct tms *Dummy __attribute__((unused))) { return (long)GetTickCount(); } int inet_aton(const char *AddrStr, struct in_addr *Addr) { Addr->s_addr = inet_addr(AddrStr); return 1; } char *StrError(unsigned int ErrNo) { static char Msg[1000]; #if !defined WINCE FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg, sizeof (Msg), NULL); #else short WideMsg[1000]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg, sizeof (WideMsg) / 2, NULL); if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof (Msg), NULL, NULL) == 0) strcpy(Msg, "[cannot convert string]"); #endif return Msg; } void PError(char *Str) { fprintf(stderr, "ERROR - %s: %s", Str, StrError(GetLastError())); } void WinSockPError(char *Str) { fprintf(stderr, "ERROR - %s: %s", Str, StrError(WSAGetLastError())); } // XXX - not thread-safe, which is okay for our purposes void *dlopen(char *Name, int Flags __attribute__((unused))) { #if !defined WINCE return (void *)LoadLibrary(Name); #else short WideName[1000]; MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName)); return (void *)LoadLibrary(WideName); #endif } int dlclose(void *Handle) { FreeLibrary((HMODULE)Handle); return 0; } void *dlsym(void *Handle, char *Name) { #if !defined WINCE return GetProcAddress((HMODULE)Handle, Name); #else short WideName[1000]; MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName)); return GetProcAddress((HMODULE)Handle, WideName); #endif } char *dlerror(void) { return StrError(GetLastError()); } #define NS_INADDRSZ 4 #define NS_IN6ADDRSZ 16 #define NS_INT16SZ 2 static int inet_pton4(const char *src, unsigned char *dst) { int saw_digit, octets, ch; u_char tmp[NS_INADDRSZ], *tp; saw_digit = 0; octets = 0; *(tp = tmp) = 0; while ((ch = *src++) != '\0') { if (ch >= '0' && ch <= '9') { unsigned int new = *tp * 10 + (ch - '0'); if (new > 255) return (0); *tp = new; if (!saw_digit) { if (++octets > 4) return (0); saw_digit = 1; } } else if (ch == '.' && saw_digit) { if (octets == 4) return (0); *++tp = 0; saw_digit = 0; } else return (0); } if (octets < 4) return (0); memcpy(dst, tmp, NS_INADDRSZ); return (1); } static int inet_pton6(const char *src, unsigned char *dst) { static const char xdigits[] = "0123456789abcdef"; u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; const char *curtok; int ch, saw_xdigit; u_int val; tp = memset(tmp, '\0', NS_IN6ADDRSZ); endp = tp + NS_IN6ADDRSZ; colonp = NULL; if (*src == ':') if (*++src != ':') return (0); curtok = src; saw_xdigit = 0; val = 0; while ((ch = tolower (*src++)) != '\0') { const char *pch; pch = strchr(xdigits, ch); if (pch != NULL) { val <<= 4; val |= (pch - xdigits); if (val > 0xffff) return (0); saw_xdigit = 1; continue; } if (ch == ':') { curtok = src; if (!saw_xdigit) { if (colonp) return (0); colonp = tp; continue; } else if (*src == '\0') { return (0); } if (tp + NS_INT16SZ > endp) return (0); *tp++ = (u_char) (val >> 8) & 0xff; *tp++ = (u_char) val & 0xff; saw_xdigit = 0; val = 0; continue; } if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) { tp += NS_INADDRSZ; saw_xdigit = 0; break; } return (0); } if (saw_xdigit) { if (tp + NS_INT16SZ > endp) return (0); *tp++ = (u_char) (val >> 8) & 0xff; *tp++ = (u_char) val & 0xff; } if (colonp != NULL) { const int n = tp - colonp; int i; if (tp == endp) return (0); for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if (tp != endp) return (0); memcpy(dst, tmp, NS_IN6ADDRSZ); return (1); } int inet_pton(int af, const char *src, void *dst) { switch (af) { case AF_INET: return (inet_pton4(src, dst)); case AF_INET6: return (inet_pton6(src, dst)); default: return -1; } } static char *inet_ntop4(const unsigned char *src, char *dst, int size) { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof "255.255.255.255"]; if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) return (NULL); return strcpy(dst, tmp); } static char *inet_ntop6(const unsigned char *src, char *dst, int size) { char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; struct { int base, len; } best, cur; u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; int i; memset(words, '\0', sizeof words); for (i = 0; i < NS_IN6ADDRSZ; i += 2) words[i / 2] = (src[i] << 8) | src[i + 1]; best.base = -1; cur.base = -1; for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; tp = tmp; for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) *tp++ = ':'; continue; } if (i != 0) *tp++ = ':'; if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) return (NULL); tp += strlen(tp); break; } tp += sprintf(tp, "%x", words[i]); } if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) *tp++ = ':'; *tp++ = '\0'; if ((tp - tmp) > size) return (NULL); return strcpy(dst, tmp); } char *inet_ntop(int af, const void *src, char *dst, int size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, size)); case AF_INET6: return (inet_ntop6(src, dst, size)); default: return (NULL); } } int isatty(int fd) { #if !defined WINCE HANDLE Hand; CONSOLE_SCREEN_BUFFER_INFO Info; unsigned long Events; if (fd == 0) { Hand = GetStdHandle(STD_INPUT_HANDLE); return GetNumberOfConsoleInputEvents(Hand, &Events); } else if (fd == 1) { Hand = GetStdHandle(STD_OUTPUT_HANDLE); return GetConsoleScreenBufferInfo(Hand, &Info); } else if (fd == 2) { Hand = GetStdHandle(STD_ERROR_HANDLE); return GetConsoleScreenBufferInfo(Hand, &Info); } return -1; #else return 0; #endif } #define CHUNK_SIZE 512 /* and we emulate a real write(2) syscall using send() */ int write(int fd, const void *buf, unsigned int count) { size_t written = 0; while (written < count) { ssize_t rc = send(fd, buf+written, min(count-written, CHUNK_SIZE), 0); if (rc <= 0) { break; } written += rc; } return written; }