summaryrefslogtreecommitdiffstats
path: root/src/kvilib/net/kvi_netutils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/kvilib/net/kvi_netutils.cpp')
-rw-r--r--src/kvilib/net/kvi_netutils.cpp1504
1 files changed, 1504 insertions, 0 deletions
diff --git a/src/kvilib/net/kvi_netutils.cpp b/src/kvilib/net/kvi_netutils.cpp
new file mode 100644
index 00000000..0cdb8b02
--- /dev/null
+++ b/src/kvilib/net/kvi_netutils.cpp
@@ -0,0 +1,1504 @@
+//=============================================================================
+
+//
+
+// File : kvi_netutlis.cpp
+
+// Creation date : Sun Jun 18 2000 18:37:27 by Szymon Stefanek
+
+//
+
+// This file is part of the KVirc irc client distribution
+
+// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot net)
+
+//
+
+// This program is FREE software. You can redistribute it and/or
+
+// modify it under the terms of the GNU General Public License
+
+// as published by the Free Software Foundation; either version 2
+
+// of the License, or (at your opinion) any later version.
+
+//
+
+// This program is distributed in the HOPE that it will be USEFUL,
+
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+// See the GNU General Public License for more details.
+
+//
+
+// You should have received a copy of the GNU General Public License
+
+// along with this program. If not, write to the Free Software Foundation,
+
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+//
+
+//=============================================================================
+
+// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGH!
+// This effect is caused by the combination of broken CVS installation and
+// the ugly windows "text mode" files
+
+#define __KVILIB__
+
+
+
+
+
+#define _KVI_NETUTILS_CPP_
+
+
+
+#include "kvi_netutils.h"
+
+#include "kvi_memmove.h"
+#include <qstringlist.h>
+
+
+#ifndef COMPILE_ON_WINDOWS
+
+#include <sys/time.h> // struct timeval
+
+#endif
+
+
+
+#include <sys/types.h>
+
+
+
+#include "kvi_qstring.h"
+
+
+
+#ifndef COMPILE_ON_WINDOWS
+
+ #include <unistd.h>
+
+ #include <netdb.h>
+
+#endif
+
+
+
+#ifdef COMPILE_GET_INTERFACE_ADDRESS
+
+ #include <sys/ioctl.h>
+
+ #include <net/if.h>
+
+#endif //COMPILE_GET_INTERFACE_ADDRESS
+
+
+
+#ifndef HAVE_INET_ATON
+
+
+
+
+
+// FIXME: #warning "Your system lacks the inet_aton function,"
+
+// FIXME: #warning "you're trying to compile this file without"
+
+// FIXME: #warning "the config.h created by the configure script,"
+
+// FIXME: #warning "Using own internal implementation of inet_aton."
+
+
+
+#include <ctype.h>
+
+
+
+
+
+// Need own inet_aton implementation
+
+
+
+//
+
+// Check whether "cp" is a valid ascii representation
+
+// of an Internet address and convert to a binary address.
+
+// Returns 1 if the address is valid, 0 if not.
+
+// This replaces inet_addr, the return value from which
+
+// cannot distinguish between failure and a local broadcast address.
+
+//
+
+// Original code comes from the ircd source.
+
+//
+
+
+
+bool kvi_stringIpToBinaryIp(const char *szIp,struct in_addr *address)
+
+{
+
+ register unsigned long val;
+
+ register int base, n;
+
+ register char c;
+
+ unsigned int parts[4];
+
+ register unsigned int *pp = parts;
+
+ if(!szIp)return false;
+
+ c = *szIp;
+
+ for(;;){
+
+ // Collect number up to ``.''.
+
+ // Values are specified as for C:
+
+ // 0x=hex, 0=octal, isdigit=decimal.
+
+ if(!isdigit(c))return false;
+
+ val = 0;
+
+ base = 10;
+
+ if(c == '0'){
+
+ c = *++szIp;
+
+ if((c == 'x')||(c == 'X'))base = 16, c = *++szIp;
+
+ else base = 8;
+
+ }
+
+ for (;;) {
+
+ if(isascii(c) && isdigit(c)) {
+
+ val = (val * base) + (c - '0');
+
+ c = *++szIp;
+
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+
+ val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
+
+ c = *++szIp;
+
+ } else break;
+
+ }
+
+ if(c == '.'){
+
+ // Internet format:
+
+ // a.b.c.d
+
+ // a.b.c (with c treated as 16 bits)
+
+ // a.b (with b treated as 24 bits)
+
+ if(pp >= (parts + 3)) return false;
+
+ *pp++ = val;
+
+ c = *++szIp;
+
+ } else break;
+
+ }
+
+ // Check for trailing characters.
+
+ if ((c != '\0') && (!isascii(c) || !isspace(c)))return false;
+
+ // Concact the address according to
+
+ // the number of parts specified.
+
+ n = pp - parts + 1;
+
+ switch (n) {
+
+ case 0: return false; // initial nondigit
+
+ case 1: break; // a -- 32 bits
+
+ case 2: // a.b -- 8.24 bits
+
+ if(val > 0xffffff) return false;
+
+ val |= parts[0] << 24;
+
+ break;
+
+ case 3: // a.b.c -- 8.8.16 bits
+
+ if(val > 0xffff)return false;
+
+ val |= (parts[0] << 24) | (parts[1] << 16);
+
+ break;
+
+ case 4: // a.b.c.d -- 8.8.8.8 bits
+
+ if(val > 0xff)return false;
+
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+
+ break;
+
+ }
+
+ if(address)address->s_addr = htonl(val);
+
+ return true;
+
+}
+
+
+
+#else //!HAVE_INET_ATON
+
+
+
+bool kvi_stringIpToBinaryIp(const char *szIp,struct in_addr *address)
+
+{
+
+ if(!szIp)return false;
+
+ return (inet_aton(szIp,address) != 0);
+
+}
+
+
+
+#endif //!HAVE_INET_ATON
+
+
+
+#ifndef HAVE_INET_NTOA
+
+
+
+// FIXME: #warning "Your system lacks the inet_ntoa function,"
+
+// FIXME: #warning "you're trying to compile this file without"
+
+// FIXME: #warning "the config.h created by the configure script,"
+
+// FIXME: #warning "Using own internal implementation of inet_ntoa."
+
+
+
+//
+
+// Original code comes from the ircd source.
+
+//
+
+
+
+bool kvi_binaryIpToStringIp(struct in_addr in,QString &szBuffer)
+
+{
+
+ unsigned char *s = (unsigned char *)&in;
+
+ int a,b,c,d;
+
+ a = (int)*s++;
+
+ b = (int)*s++;
+
+ c = (int)*s++;
+
+ d = (int)*s;
+
+ szBuffer.sprintf("%d.%d.%d.%d", a,b,c,d );
+
+ return true;
+
+}
+
+
+
+#else //HAVE_INET_NTOA
+
+
+
+bool kvi_binaryIpToStringIp(struct in_addr in,QString &szBuffer)
+
+{
+
+// FIXME: #warning "This is NOT thread safe!"
+
+ char * ptr = inet_ntoa(in);
+
+ if(!ptr)return false;
+
+ szBuffer = ptr;
+
+ return true;
+
+}
+
+
+
+#endif //HAVE_INET_NTOA
+
+
+
+bool kvi_isValidStringIp(const char *szIp)
+
+{
+
+ struct in_addr address;
+
+ if(!szIp)return false;
+
+ if(!isdigit(*szIp))return false;
+
+ return kvi_stringIpToBinaryIp(szIp,&address);
+
+}
+
+
+
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+
+
+#ifdef COMPILE_ON_WINDOWS
+
+
+
+//#include <stdlib.h>
+
+//#include <sys/socket.h>
+
+//#include <arpa/inet.h>/
+
+//#include <errno.h>
+
+//#include "dietfeatures.h"
+
+
+
+static unsigned int scan_ip6(const char *s,char ip[16])
+
+{
+
+ unsigned int i;
+
+ unsigned int len=0;
+
+ unsigned long u;
+
+
+
+ char suffix[16];
+
+ unsigned int prefixlen=0;
+
+ unsigned int suffixlen=0;
+
+
+
+ for (i=0; i<16; i++) ip[i]=0;
+
+
+
+ for (;;) {
+
+ if (*s == ':') {
+
+ len++;
+
+ if (s[1] == ':') { /* Found "::", skip to part 2 */
+
+ s+=2;
+
+ len++;
+
+ break;
+
+ }
+
+ s++;
+
+ }
+
+ {
+
+ char *tmp;
+
+ u=strtoul(s,&tmp,16);
+
+ i=tmp-s;
+
+ }
+
+
+
+ if (!i) return 0;
+
+ if (prefixlen==12 && s[i]=='.') {
+
+ /* the last 4 bytes may be written as IPv4 address */
+
+ if (kvi_stringIpToBinaryIp(s,(struct in_addr*)(ip+12)))
+
+ return i+len;
+
+ else
+
+ return 0;
+
+ }
+
+ ip[prefixlen++] = (u >> 8);
+
+ ip[prefixlen++] = (u & 255);
+
+ s += i; len += i;
+
+ if (prefixlen==16)
+
+ return len;
+
+ }
+
+
+
+/* part 2, after "::" */
+
+ for (;;) {
+
+ if (*s == ':') {
+
+ if (suffixlen==0)
+
+ break;
+
+ s++;
+
+ len++;
+
+ } else if (suffixlen!=0)
+
+ break;
+
+ {
+
+ char *tmp;
+
+ u=strtol(s,&tmp,16);
+
+ i=tmp-s;
+
+ }
+
+ if (!i) {
+
+ if (*s) len--;
+
+ break;
+
+ }
+
+ if (suffixlen+prefixlen<=12 && s[i]=='.') {
+
+ if (kvi_stringIpToBinaryIp(s,(struct in_addr*)(suffix+suffixlen))) {
+
+ suffixlen+=4;
+
+ len+=(unsigned int)strlen(s);
+
+ break;
+
+ } else
+
+ prefixlen=12-suffixlen; /* make end-of-loop test true */
+
+ }
+
+ suffix[suffixlen++] = (u >> 8);
+
+ suffix[suffixlen++] = (u & 255);
+
+ s += i; len += i;
+
+ if (prefixlen+suffixlen==16)
+
+ break;
+
+ }
+
+ for (i=0; i<suffixlen; i++)
+
+ ip[16-suffixlen+i] = suffix[i];
+
+ return len;
+
+}
+
+
+
+#ifndef WIN2K
+
+
+
+int inet_pton(int AF, const char *CP, void *BUF) {
+
+ int len;
+
+ if (AF==AF_INET) {
+
+ if (!kvi_stringIpToBinaryIp(CP,(struct in_addr*)BUF))
+
+ return 0;
+
+ } else if (AF==AF_INET6) {
+
+ if (CP[len=scan_ip6(CP,(char *)BUF)])
+
+ return 0;
+
+ } else {
+
+ errno=WSAEPFNOSUPPORT;
+
+ return -1;
+
+ }
+
+ return 1;
+
+}
+
+
+
+#endif //WIN2K
+
+
+
+//#include <sys/socket.h>
+
+//#include <arpa/inet.h>
+
+
+
+//extern char *inet_ntoa_r(struct in_addr in,char* buf);
+
+
+
+static const unsigned char V4mappedprefix[12]={0,0,0,0,0,0,0,0,0,0,0xff,0xff};
+
+
+
+static char tohex(char hexdigit) {
+
+ return hexdigit>9?hexdigit+'a'-10:hexdigit+'0';
+
+}
+
+
+
+static int fmt_xlong(char* s,unsigned int i)
+
+{
+
+ char* bak=s;
+
+ *s=tohex((i>>12)&0xf); if (s!=bak || *s!='0') ++s;
+
+ *s=tohex((i>>8)&0xf); if (s!=bak || *s!='0') ++s;
+
+ *s=tohex((i>>4)&0xf); if (s!=bak || *s!='0') ++s;
+
+ *s=tohex(i&0xf);
+
+ return s-bak+1;
+
+}
+
+
+
+static unsigned int i2a(char* dest,unsigned int x)
+
+{
+
+ register unsigned int tmp=x;
+
+ register unsigned int len=0;
+
+ if (x>=100) { *dest++=tmp/100+'0'; tmp=tmp%100; ++len; }
+
+ if (x>=10) { *dest++=tmp/10+'0'; tmp=tmp%10; ++len; }
+
+ *dest++=tmp+'0';
+
+ return len+1;
+
+}
+
+
+
+char *inet_ntoa_r(struct in_addr in,char* buf)
+
+{
+
+ unsigned int len;
+
+ unsigned char *ip=(unsigned char*)&in;
+
+ len=i2a(buf,ip[0]); buf[len]='.'; ++len;
+
+ len+=i2a(buf+ len,ip[1]); buf[len]='.'; ++len;
+
+ len+=i2a(buf+ len,ip[2]); buf[len]='.'; ++len;
+
+ len+=i2a(buf+ len,ip[3]); buf[len]=0;
+
+ return buf;
+
+}
+
+
+
+
+
+unsigned int fmt_ip6(char *s,const char ip[16])
+
+{
+
+ unsigned int len;
+
+ unsigned int i;
+
+ unsigned int temp;
+
+ unsigned int compressing; // 0 not compressing , 1 compressing now , 2 already compressed once
+
+
+
+ len = 0;
+
+ compressing = 0;
+
+
+
+ for(int j=0;j<16;j+=2)
+
+ {
+
+ if (j==12 && !memcmp(ip,V4mappedprefix,12))
+
+ {
+
+ inet_ntoa_r(*(struct in_addr*)(ip+12),s);
+
+ temp=(unsigned int)strlen(s);
+
+ return len+temp;
+
+ }
+
+ temp = ((unsigned long) (unsigned char) ip[j] << 8) + (unsigned long) (unsigned char) ip[j+1];
+
+ if(temp == 0)
+
+ {
+
+ if(compressing == 0)
+
+ {
+
+ compressing=1;
+
+ if (j==0)
+
+ {
+
+ *s++=':';
+
+ ++len;
+
+ }
+
+ }
+
+ } else {
+
+ if(compressing == 1)
+
+ {
+
+ compressing=2; // don't do it again
+
+ *s++=':'; ++len;
+
+ }
+
+ i = fmt_xlong(s,temp);
+
+ len += i;
+
+ s += i;
+
+ if (j<14)
+
+ {
+
+ *s++ = ':';
+
+ ++len;
+
+ }
+
+ }
+
+ }
+
+ if(compressing == 1)
+
+ {
+
+ *s++=':';
+
+ ++len;
+
+ }
+
+ *s=0;
+
+ return len;
+
+}
+
+
+
+const char* inet_ntop(int AF, const void *CP, char *BUF, size_t LEN)
+
+{
+
+ char buf[100];
+
+ size_t len;
+
+ if (AF==AF_INET)
+
+ {
+
+ inet_ntoa_r(*(struct in_addr*)CP,buf);
+
+ len=strlen(buf);
+
+ } else if (AF==AF_INET6)
+
+ {
+
+ len=fmt_ip6(buf,(char *)CP);
+
+ } else
+
+ return 0;
+
+ if (len<LEN)
+
+ {
+
+ strcpy(BUF,buf);
+
+ return BUF;
+
+ }
+
+ return 0;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+#endif
+
+
+
+
+
+bool kvi_stringIpToBinaryIp_V6(const char *szIp,struct in6_addr *address)
+
+{
+
+ if(!szIp)return false;
+
+ return (inet_pton(AF_INET6,szIp,(void *)address) == 1);
+
+}
+
+
+
+bool kvi_isValidStringIp_V6(const char *szIp)
+
+{
+
+ struct in6_addr address;
+
+ if(!szIp)return false;
+
+ return kvi_stringIpToBinaryIp_V6(szIp,&address);
+
+}
+
+
+
+
+
+
+
+bool kvi_binaryIpToStringIp_V6(struct in6_addr in,QString &szBuffer)
+
+{
+
+ char buf[46];
+
+ bool bRet = inet_ntop(AF_INET6,(void *)&in,buf,46);
+
+ szBuffer= buf;
+
+ return bRet;
+
+}
+
+
+
+#endif
+
+
+
+#include <errno.h>
+
+
+
+bool kvi_select(int fd,bool * bCanRead,bool * bCanWrite,int iUSecs)
+
+{
+
+ // FIXME: This stuff should DIE!
+
+ fd_set rs;
+
+ fd_set ws;
+
+ FD_ZERO(&rs);
+
+ FD_ZERO(&ws);
+
+ FD_SET(fd,&rs);
+
+ FD_SET(fd,&ws);
+
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+
+ tv.tv_usec = iUSecs;
+
+ int ret = select(fd + 1,&rs,&ws,0,&tv);
+
+ if(ret < 1)return false; // EINTR or ENOSTUFFATALL
+
+ *bCanRead = FD_ISSET(fd,&rs);
+
+ *bCanWrite = FD_ISSET(fd,&ws);
+
+ return true;
+
+}
+
+
+
+namespace KviNetUtils
+
+{
+
+ bool stringIpToBinaryIp(const QString &szStringIp,struct in_addr * address)
+ {
+#ifndef HAVE_INET_ATON
+ QString szAddr = szStringIp.simplifyWhiteSpace();
+ Q_UINT32 iAddr=0;
+ QStringList ipv4 = QStringList::split(".", szAddr, FALSE);
+ if (ipv4.count() == 4) {
+ int i = 0;
+ bool ok = TRUE;
+ while(ok && i < 4) {
+ uint byteValue = ipv4[i].toUInt(&ok);
+ if ( (byteValue > 255) && ok )
+ ok = FALSE;
+ if (ok)
+ iAddr = (iAddr << 8) + byteValue;
+ ++i;
+ }
+ if (ok)
+ {
+ if(address)address->s_addr = htonl(iAddr);
+ return true;
+ }
+ }
+ return FALSE;
+#else //HAVE_INET_ATON
+ if(szStringIp.isEmpty())return false;
+ return (inet_aton(KviQString::toUtf8(szStringIp).data(),address) != 0);
+#endif //HAVE_INET_ATON
+ }
+
+
+ bool isValidStringIp(const QString &szIp)
+
+ {
+
+ struct in_addr address;
+
+ if(szIp.isEmpty())return false;
+
+ if(!szIp[0].isNumber())return false;
+
+ return stringIpToBinaryIp(szIp,&address);
+
+ }
+
+
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+ bool stringIpToBinaryIp_V6(const QString &szStringIp,struct in6_addr * address)
+
+ {
+
+ return (inet_pton(AF_INET6,KviQString::toUtf8(szStringIp).data(),(void *)address) == 1);
+
+ }
+
+
+
+ bool isValidStringIp_V6(const QString &szIp)
+
+ {
+
+ struct in6_addr address;
+
+ if(szIp.isEmpty())return false;
+
+ return stringIpToBinaryIp_V6(szIp,&address);
+
+ }
+
+ bool binaryIpToStringIp_V6(struct in6_addr in,QString &szBuffer)
+ {
+ char buf[46];
+ bool bRet = inet_ntop(AF_INET6,(void *)&in,buf,46);
+ szBuffer= buf;
+ return bRet;
+ }
+
+
+#endif //COMPILE_IPV6_SUPPORT
+
+
+
+ bool binaryIpToStringIp(struct in_addr in,QString &szBuffer)
+
+ {
+
+ char * ptr = inet_ntoa(in);
+
+ if(!ptr)return false;
+
+ szBuffer = ptr;
+
+ return true;
+
+ }
+
+
+
+ bool isRoutableIpString(const QString &szIpString)
+
+ {
+
+ struct in_addr a;
+
+ if(szIpString.isEmpty())return false;
+
+ stringIpToBinaryIp(szIpString,&a);
+
+ return isRoutableIp((const char *)&a);
+
+ }
+
+
+
+ bool isRoutableIp(const char * ipaddr)
+
+ {
+
+ if(!ipaddr)return false;
+
+ const unsigned char * ip = (const unsigned char *)ipaddr;
+
+ if(ip[0] == 0)return false; // old-style broadcast
+
+ if(ip[0] == 10)return false; // Class A VPN
+
+ if(ip[0] == 127)return false; // loopback
+
+ if((ip[0] == 172) && (ip[1] >= 16) && (ip[1] <= 31))return false; // Class B VPN
+
+ if((ip[0] == 192) && (ip[1] == 168))return false; // Class C VPN
+
+ if((ip[0] == 169) && (ip[1] == 254))return false; // APIPA
+
+ if((ip[0] == 192) && (ip[1] == 0) && (ip[2] == 2))return false; // Class B VPN
+
+ if(ip[0] >= 224)return false; // class D multicast and class E reserved
+
+
+
+ return true;
+
+ }
+
+
+
+ bool getInterfaceAddress(const QString &szInterfaceName,QString &szBuffer)
+
+ {
+
+#ifdef COMPILE_GET_INTERFACE_ADDRESS
+
+ struct sockaddr *sa;
+
+ struct sockaddr_in *sin;
+
+ struct ifreq ifr;
+
+ int len = szInterfaceName.length();
+
+ if(len > (IFNAMSIZ - 1))return false; // invalid interface anyway
+
+
+
+ kvi_memmove(ifr.ifr_name,KviQString::toUtf8(szInterfaceName).data(),len + 1);
+
+
+
+ int fd = socket(AF_INET,SOCK_STREAM,0);
+
+ if(fd < 0)return false;
+
+
+
+ if(ioctl(fd,SIOCGIFADDR,&ifr) == -1)return false; // supports only IPV4 ?
+
+
+
+ close(fd);
+
+
+
+ sa = (struct sockaddr *)&(ifr.ifr_addr);
+
+
+
+ if (sa->sa_family != AF_INET) return false;
+
+ sin = (struct sockaddr_in*) sa;
+
+ return binaryIpToStringIp(sin->sin_addr,szBuffer);
+
+ // (this seems to work for AF_INET only anyway)
+
+#else //!COMPILE_GET_INTERFACE_ADDRESS
+
+ return false;
+
+#endif //!COMPILE_GET_INTERFACE_ADDRESS
+
+ }
+
+
+
+ void formatNetworkBandwidthString(QString &szBuffer,unsigned int uBytesPerSec)
+
+ {
+
+ if(uBytesPerSec > (1024 * 1024))
+
+ {
+
+ unsigned int uMB = uBytesPerSec / (1024 * 1024);
+
+ unsigned int uRem = ((uBytesPerSec % (1024 * 1024)) * 100) / (1024 * 1024);
+
+ KviQString::sprintf(szBuffer,"%u.%u%u MB/s",uMB,uRem / 10,uRem % 10);
+
+ return;
+
+ }
+
+ if(uBytesPerSec >= 1024)
+
+ {
+
+ unsigned int uKB = uBytesPerSec / 1024;
+
+ unsigned int uRem = ((uBytesPerSec % 1024) * 100) / 1024;
+
+ KviQString::sprintf(szBuffer,"%u.%u%u KB/s",uKB,uRem / 10,uRem % 10);
+
+ return;
+
+ }
+
+ KviQString::sprintf(szBuffer,"%u B/s",uBytesPerSec);
+
+ }
+
+
+
+
+
+};
+
+
+
+bool kvi_getInterfaceAddress(const char * ifname,QString &buffer)
+
+{
+
+ debug("kvi_getInterfaceAddress is deprecated: use KviNetUtils::getInterfaceAddress");
+
+ QString szRet;
+
+ bool bRes = KviNetUtils::getInterfaceAddress(QString(ifname),szRet);
+
+ buffer = szRet;
+
+ return bRes;
+
+}
+
+
+
+bool kvi_isRoutableIpString(const char * ipstring)
+
+{
+
+ struct in_addr a;
+
+ if(!ipstring)return false;
+
+ kvi_stringIpToBinaryIp(ipstring,&a);
+
+ return kvi_isRoutableIp((const char *)&a);
+
+}
+
+
+
+bool kvi_isRoutableIp(const char * ipaddr)
+
+{
+
+ if(!ipaddr)return false;
+
+ const unsigned char * ip = (const unsigned char *)ipaddr;
+
+ if(ip[0] == 0)return false; // old-style broadcast
+
+ if(ip[0] == 10)return false; // Class A VPN
+
+ if(ip[0] == 127)return false; // loopback
+
+ if((ip[0] == 172) && (ip[1] >= 16) && (ip[1] <= 31))return false; // Class B VPN
+
+ if((ip[0] == 192) && (ip[1] == 168))return false; // Class C VPN
+
+ if((ip[0] == 169) && (ip[1] == 254))return false; // APIPA
+
+ if((ip[0] == 192) && (ip[1] == 0) && (ip[2] == 2))return false; // Class B VPN
+
+ if(ip[0] >= 224)return false; // class D multicast and class E reserved
+
+
+
+ return true;
+
+}
+
+
+
+bool kvi_getLocalHostAddress(QString &buffer)
+
+{
+
+ // This will work only on windoze...
+
+ char buf[1024];
+
+ if(gethostname(buf,1024) != 0)return false;
+
+ struct hostent * h = gethostbyname(buf);
+
+ if(!h)return false;
+
+ QString tmp;
+
+ int i=0;
+
+ while(h->h_addr_list[i])
+
+ {
+
+ if(kvi_binaryIpToStringIp(*((struct in_addr *)(h->h_addr_list[i])),tmp))
+
+ {
+
+ if(kvi_isRoutableIp(h->h_addr_list[i]))
+
+ {
+
+ buffer = tmp;
+
+ return true;
+
+ }
+
+ }
+
+ i++;
+
+ }
+
+ buffer = tmp;
+
+ return true;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+KviSockaddr::KviSockaddr(const char * szIpAddress,kvi_u32_t uPort,bool bIpV6,bool bUdp)
+
+{
+ struct addrinfo hints;
+ kvi_memset((void *)&hints,0,sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+#ifdef COMPILE_IPV6_SUPPORT
+ hints.ai_family = bIpV6 ? PF_INET6 : PF_INET;
+#else
+ hints.ai_family = PF_INET;
+#endif
+
+ hints.ai_socktype = bUdp ? SOCK_DGRAM : SOCK_STREAM;
+
+ hints.ai_protocol = 0;
+ m_pData = 0;
+ KviStr szPort(KviStr::Format,"%u",uPort);
+ getaddrinfo(szIpAddress,szPort.ptr(),&hints,(struct addrinfo **)&m_pData);
+
+}
+
+
+KviSockaddr::KviSockaddr(kvi_u32_t uPort,bool bIpV6,bool bUdp) // passive sockaddr
+
+{
+ struct addrinfo hints;
+ kvi_memset((void *)&hints,0,sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+#ifdef COMPILE_IPV6_SUPPORT
+ hints.ai_family = bIpV6 ? PF_INET6 : PF_INET;
+#else
+ hints.ai_family = PF_INET;
+#endif
+ hints.ai_socktype = bUdp ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = 0;
+ m_pData = 0;
+ KviStr szPort(KviStr::Format,"%u",uPort);
+ getaddrinfo(0,szPort.ptr(),&hints,(struct addrinfo **)&m_pData);
+
+}
+
+
+
+KviSockaddr::~KviSockaddr()
+
+{
+
+ if(m_pData)
+
+ {
+
+ freeaddrinfo((struct addrinfo *)m_pData);
+
+ m_pData = 0;
+
+ }
+
+}
+
+
+
+struct sockaddr * KviSockaddr::socketAddress()
+
+{
+
+ if(!m_pData)return 0;
+
+ return ((struct addrinfo *)m_pData)->ai_addr;
+
+}
+
+
+
+size_t KviSockaddr::addressLength()
+
+{
+
+ if(!m_pData)return 0;
+
+ return ((struct addrinfo *)m_pData)->ai_addrlen;
+
+}
+
+
+
+int KviSockaddr::addressFamily()
+
+{
+
+ if(!m_pData)return 0;
+
+ return ((struct addrinfo *)m_pData)->ai_family;
+
+}
+
+
+
+bool KviSockaddr::isIpV6()
+
+{
+
+ if(!m_pData)return false;
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+ return false;
+
+#else
+
+ return (addressFamily() == AF_INET6);
+
+#endif
+
+}
+
+
+
+kvi_u32_t KviSockaddr::port()
+
+{
+ if(!m_pData)return 0;
+#ifdef COMPILE_IPV6_SUPPORT
+ switch(((struct addrinfo *)m_pData)->ai_family)
+ {
+ case AF_INET:
+ return ntohs(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_port);
+ break;
+ case AF_INET6:
+ return ntohs(((struct sockaddr_in6 *)(((struct addrinfo *)m_pData)->ai_addr))->sin6_port);
+ break;
+ }
+ return 0;
+#else
+ return ntohs(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_port);
+#endif
+
+}
+
+
+
+bool KviSockaddr::getStringAddress(QString &szBuffer)
+
+{
+
+ if(!m_pData)return 0;
+
+#ifdef COMPILE_IPV6_SUPPORT
+
+ switch(((struct addrinfo *)m_pData)->ai_family)
+
+ {
+
+ case AF_INET:
+
+ return kvi_binaryIpToStringIp(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_addr,szBuffer);
+
+ break;
+
+ case AF_INET6:
+
+ return kvi_binaryIpToStringIp_V6(((struct sockaddr_in6 *)(((struct addrinfo *)m_pData)->ai_addr))->sin6_addr,szBuffer);
+
+ break;
+
+ }
+
+ return false;
+
+#else
+
+ return kvi_binaryIpToStringIp(((struct sockaddr_in *)(((struct addrinfo *)m_pData)->ai_addr))->sin_addr,szBuffer);
+
+#endif
+
+}
+