📄 inaddr.cpp
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.// // 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 option) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by// the GNU General Public License. //// This exception applies only to the code released under the name GNU// Common C++. If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include <cc++/config.h>#include <cc++/export.h>#include <cc++/address.h>#include "private.h"#include <cstdlib>#ifdef CCXX_NAMESPACESnamespace ost {#endif#ifndef WIN32Mutex IPV4Address::mutex;#endifconst IPV4MulticastValidator IPV4Multicast::validator;void IPV4MulticastValidator::operator()(const in_addr address) const{#ifdef CCXX_EXCEPTIONS // "0.0.0.0" is always accepted, as it is an "empty" address. if ( (address.s_addr != INADDR_ANY) && (address.s_addr & MCAST_VALID_MASK) != MCAST_VALID_VALUE ) { throw "Multicast address not in the valid range: from 224.0.0.1 through 239.255.255.255"; }#endif}IPV4Address::IPV4Address(const IPV4Validator *_validator) : validator(_validator), ipaddr(NULL), addr_count(0), hostname(NULL){ *this = (long unsigned int)INADDR_ANY;}IPV4Address::IPV4Address(const char *address, const IPV4Validator *_validator) : validator(_validator), ipaddr(NULL), addr_count(0), hostname(NULL){ if ( this->validator ) this->validator = validator; if(address == 0 || !strcmp(address, "*")) setAddress(NULL); else setAddress(address);}IPV4Address::IPV4Address(struct in_addr addr, const IPV4Validator *_validator) : validator(_validator), ipaddr(NULL), hostname(NULL){ if ( this->validator ){ this->validator = validator; (*validator)(addr); } addr_count = 1; ipaddr = new struct in_addr[1]; ipaddr[0] = addr;}IPV4Address::IPV4Address(const IPV4Address &rhs) : validator(rhs.validator), addr_count(rhs.addr_count), hostname(NULL){ ipaddr = new struct in_addr[addr_count]; memcpy(ipaddr, rhs.ipaddr, sizeof(struct in_addr) * addr_count);}IPV4Address::~IPV4Address(){ if(ipaddr) { delete[] ipaddr; ipaddr = NULL; } if(hostname) { delString(hostname); hostname = NULL; }}struct in_addr IPV4Address::getAddress(void) const{ return ipaddr[0];}struct in_addr IPV4Address::getAddress(size_t i) const{ return (i < addr_count ? ipaddr[i] : ipaddr[0]);}bool IPV4Address::isInetAddress(void) const{ struct in_addr addr; memset(&addr, 0, sizeof(addr)); if(memcmp(&addr, &ipaddr[0], sizeof(addr))) return true; return false;}IPV4Address &IPV4Address::operator=(const char *str){ if(str == 0 || !strcmp(str, "*")) str = "0.0.0.0"; setAddress(str); return *this;}IPV4Address &IPV4Address::operator=(struct in_addr addr){ if(ipaddr) delete[] ipaddr; if ( validator ) (*validator)(addr); addr_count = 1; ipaddr = new struct in_addr[1]; ipaddr[0] = addr; if(hostname) delString(hostname); hostname = NULL; return *this;}IPV4Address &IPV4Address::operator=(unsigned long addr){ if ( validator ) (*validator)(*reinterpret_cast<in_addr*>(&addr)); if(ipaddr) delete[] ipaddr; addr_count = 1; ipaddr = new struct in_addr[1]; memcpy(ipaddr, &addr, sizeof(struct in_addr)); if(hostname) delString(hostname); hostname = NULL; return *this; }IPV4Address &IPV4Address::operator=(const IPV4Address &rhs){ if(this == &rhs) return *this; addr_count = rhs.addr_count; if(ipaddr) delete[] ipaddr; ipaddr = new struct in_addr[addr_count]; memcpy(ipaddr, rhs.ipaddr, sizeof(struct in_addr) * addr_count); validator = rhs.validator; if(hostname) delString(hostname); hostname = NULL; return *this;}bool IPV4Address::operator==(const IPV4Address &a) const{ const IPV4Address *smaller, *larger; size_t s, l; if(addr_count > a.addr_count) { smaller = &a; larger = this; } else { smaller = this; larger = &a; } // Loop through all addr's in the smaller and make sure // that they are all in the larger for(s = 0; s < smaller->addr_count; s++) { // bool found = false; for(l = 0; l < larger->addr_count && memcmp((char *)&ipaddr[s], (char *)&a.ipaddr[l], sizeof(struct in_addr)); l++); if(l == larger->addr_count) return false; } return true;}bool IPV4Address::operator!=(const IPV4Address &a) const{ // Impliment in terms of operator== return (*this == a ? false : true);}IPV4Host &IPV4Host::operator&=(const IPV4Mask &ma){ for(size_t i = 0; i < addr_count; i++) { struct in_addr mask = ma.getAddress(); unsigned char *a = (unsigned char *)&ipaddr[i]; unsigned char *m = (unsigned char *)&mask; for(size_t j = 0; j < sizeof(struct in_addr); ++j) *(a++) &= *(m++); } if(hostname) delString(hostname); hostname = NULL; return *this;} IPV4Host::IPV4Host(struct in_addr addr) :IPV4Address(addr) {}IPV4Host::IPV4Host(const char *host) : IPV4Address(host){ char namebuf[256]; if(!host) { gethostname(namebuf, 256); setAddress(namebuf); }}bool IPV4Address::setIPAddress(const char *host){ if(!host) return false;#if defined(WIN32) struct sockaddr_in addr; addr.sin_addr.s_addr = inet_addr(host); if ( validator ) (*validator)(addr.sin_addr); if(addr.sin_addr.s_addr == INADDR_NONE) return false; *this = addr.sin_addr.s_addr;#else struct in_addr l_addr; int ok = inet_aton(host, &l_addr); if ( validator ) (*validator)(l_addr); if ( !ok ) return false; *this = l_addr;#endif return true;}void IPV4Address::setAddress(const char *host){ if(hostname) delString(hostname); hostname = NULL; if(!host) // The way this is currently used, this can never happen { *this = (long unsigned int)htonl(INADDR_ANY); return; }#ifdef WIN32 if(!stricmp(host, "localhost")) { *this = (long unsigned int)inet_addr("127.0.0.1"); return; }#endif if(!setIPAddress(host)) { struct hostent *hp; struct in_addr **bptr;#if defined(__GLIBC__) char hbuf[8192]; struct hostent hb; int rtn; if(gethostbyname_r(host, &hb, hbuf, sizeof(hbuf), &hp, &rtn)) hp = NULL;#elif defined(sun) char hbuf[8192]; struct hostent hb; int rtn; hp = gethostbyname_r(host, &hb, hbuf, sizeof(hbuf), &rtn);#elif (defined(__osf__) || defined(WIN32)) hp = gethostbyname(host);#else mutex.enterMutex(); hp = gethostbyname(host); mutex.leaveMutex();#endif if(!hp) { if(ipaddr) delete[] ipaddr; ipaddr = new struct in_addr[1]; memset((void *)&ipaddr[0], 0, sizeof(ipaddr)); return; } // Count the number of IP addresses returned addr_count = 0; for(bptr = (struct in_addr **)hp->h_addr_list; *bptr != NULL; bptr++) { addr_count++; } // Allocate enough memory if(ipaddr) delete[] ipaddr; // Cause this was allocated in base ipaddr = new struct in_addr[addr_count]; // Now go through the list again assigning to // the member ipaddr; bptr = (struct in_addr **)hp->h_addr_list; for(unsigned int i = 0; i < addr_count; i++) { if ( validator ) (*validator)(*bptr[i]); ipaddr[i] = *bptr[i]; } }}IPV4Broadcast::IPV4Broadcast(const char *net) : IPV4Address(net){}IPV4Mask::IPV4Mask(const char *mask){ unsigned long x = 0xffffffff; int l = 32 - atoi(mask); if(setIPAddress(mask)) return; if(l < 1 || l > 32) {#ifdef CCXX_EXCEPTIONS if(Thread::getException() == Thread::throwObject) throw((IPV4Address *)this);#endif return; } *this = htonl(x << l);}const char *IPV4Address::getHostname(void) const{ struct hostent *hp = NULL; struct in_addr addr0; memset(&addr0, 0, sizeof(addr0)); if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0))) return NULL;#ifdef WIN32 memset(&addr0, 0xff, sizeof(addr0)); if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0))) return "255.255.255.255"; long a = inet_addr("127.0.0.1"); if(!memcmp(&a, &ipaddr[0], sizeof(a))) return "localhost";#endif#if defined(__GLIBC__) char hbuf[8192]; struct hostent hb; int rtn; if(gethostbyaddr_r((char *)&ipaddr[0], sizeof(addr0), AF_INET, &hb, hbuf, sizeof(hbuf), &hp, &rtn)) hp = NULL;#elif defined(sun) char hbuf[8192]; struct hostent hb; int rtn; hp = gethostbyaddr_r((char *)&ipaddr[0], (int)sizeof(addr0), (int)AF_INET, &hb, hbuf, (int)sizeof(hbuf), &rtn);#elif defined(__osf__) || defined(WIN32) hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET);#else mutex.enterMutex(); hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET); mutex.leaveMutex();#endif if(hp) { if(hostname) delString(hostname); hostname = newString(hp->h_name); return hostname; } else { return inet_ntoa(ipaddr[0]); }} IPV4Host operator&(const IPV4Host &addr, const IPV4Mask &mask){ IPV4Host temp = addr; temp &= mask; return temp;}IPV4Multicast::IPV4Multicast() : IPV4Address(&validator){ }IPV4Multicast::IPV4Multicast(const struct in_addr address) : IPV4Address(address,&validator){ }IPV4Multicast::IPV4Multicast(const char *address) : IPV4Address(address,&validator){ }#ifdef CCXX_NAMESPACES}#endif/** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -