Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

wvaddr.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Device-independent and device-specific hardware/protocol address
00006  * classes that can store themselves efficiently as well as create a
00007  * printable string version of themselves.
00008  */
00009 #ifndef _WIN32
00010 #include <netdb.h>
00011 #include <sys/socket.h>
00012 #include <sys/un.h>
00013 #include <net/if_arp.h>
00014 #endif
00015 
00016 #include "wvaddr.h"
00017 #include <assert.h>
00018 
00019 // workaround for functions called sockaddr() -- oops.
00020 typedef struct sockaddr sockaddr_bin;
00021 
00022 /* A list of Linux ARPHRD_* types, one for each element of CapType. */
00023 int WvEncap::extypes[] = {
00024 #ifdef _WIN32
00025     0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00026 #else
00027     // hardware encapsulation
00028     0, // Unknown
00029     ARPHRD_LOOPBACK,
00030     0, // Ethertap
00031     ARPHRD_ETHER,
00032     ARPHRD_ARCNET,
00033     ARPHRD_SLIP,
00034     ARPHRD_CSLIP,
00035     ARPHRD_PPP,
00036     
00037     // protocol encapsulation
00038     AF_INET, // IPv4
00039     AF_UNIX  // Unix domain socket
00040 #endif
00041 };
00042 
00043 
00044 /* Printable strings corresponding to each element of CapType */
00045 char WvEncap::strings[][20] = {
00046     // hardware encapsulation
00047     "Unknown",
00048     "Loopback",
00049     "Ethertap",
00050     "Ethernet",
00051     "ARCnet",
00052     "SLIP",
00053     "CSLIP",
00054     "PPP",
00055     
00056     // protocol encapsulation
00057     "IP", // IPv4
00058     "Unix", // Unix domain socket
00059 };
00060 
00061 
00062 /* Figure out the CapType corresponding to a Linux ARPHRD_* type or
00063  * sockaddr sa_family type.
00064  */
00065 WvEncap::WvEncap(int extype)
00066 {
00067     for (int count=0; count < NUM_ENCAP_TYPES; count++)
00068     {
00069         if (extype == extypes[count])
00070         {
00071             cap = (CapType)count;
00072             return;
00073         }
00074     }
00075     cap = Unknown;
00076 }
00077 
00078 
00079 /* Find the hash value of a WvAddr, for use with WvHashTable */
00080 unsigned WvHash(const WvAddr &addr)
00081 {
00082     return addr.WvHash();
00083 }
00084 
00085 
00086 /* Create an object of the appropriate WvAddr-derived class based on the
00087  * address and type stored in 'addr'.
00088  */
00089 WvAddr *WvAddr::gen(struct sockaddr *addr)
00090 {
00091     WvEncap encap(addr->sa_family);
00092     
00093     switch (encap.cap)
00094     {
00095     case WvEncap::Loopback:
00096         return new WvStringAddr("Loopback", WvEncap::Loopback);
00097         
00098     case WvEncap::IPv4:
00099         return new WvIPPortAddr((sockaddr_in *)addr);
00100 #ifndef _WIN32
00101     case WvEncap::ARCnet:
00102         return new WvARCnetAddr(addr);
00103         
00104     case WvEncap::Ethertap:
00105     case WvEncap::Ethernet:
00106         return new WvEtherAddr(addr);
00107 #endif
00108     default:
00109         return new WvStringAddr("Unknown", WvEncap::Unknown);
00110     }
00111 }
00112 
00113 
00114 bool WvAddr::isbroadcast() const
00115 {
00116     return false; // default is no support for broadcasts
00117 }
00118 
00119 
00120 const unsigned char *WvAddr::rawdata() const
00121 {
00122     return NULL;
00123 }
00124 
00125 
00126 size_t WvAddr::rawdata_len() const
00127 {
00128     return 0;
00129 }
00130 
00131 
00132 unsigned WvAddr::WvHash() const
00133 {
00134     unsigned hash = 0;
00135     const unsigned char *cptr, *raw = rawdata();
00136     int len = rawdata_len(), width;
00137    
00138     if (!raw || !len) return 0;
00139     width = (sizeof(hash)*8 / len) + 1;
00140     
00141     for (cptr = raw; len; len--)
00142         hash = (hash << width) ^ *(cptr++);
00143     return hash;
00144 }
00145 
00146 
00147 bool WvAddr::comparator(const WvAddr *a2, bool first_pass) const
00148 {
00149     if (type() != a2->type()) return false;    
00150 
00151     const unsigned char *raw1, *raw2;
00152     size_t len;
00153     
00154     len = rawdata_len();
00155     if (len != a2->rawdata_len())
00156         return false;
00157     
00158     raw1 = rawdata();
00159     raw2 = a2->rawdata();
00160     
00161     if (!raw1 && !raw2) return true;
00162     if (!raw1 || !raw2) return false;
00163     
00164     return !memcmp(raw1, raw2, len);
00165 }
00166 
00167 
00168 WvStringAddr::WvStringAddr(WvStringParm s, const WvEncap &_cap)
00169         : addr(s), cap(_cap)
00170 {
00171 }
00172 
00173 
00174 WvStringAddr::WvStringAddr(const struct sockaddr *_addr)
00175         : addr((char *)_addr->sa_data), cap(_addr->sa_family)
00176 {
00177 }
00178 
00179 
00180 WvStringAddr::~WvStringAddr()
00181 {
00182     // nothing to do
00183 }
00184 
00185 
00186 WvEncap WvStringAddr::encap() const
00187 {
00188     return cap;
00189 }
00190 
00191 
00192 const unsigned char *WvStringAddr::rawdata() const
00193 {
00194     return (const unsigned char *)(const char *)addr;
00195 }
00196 
00197 
00198 size_t WvStringAddr::rawdata_len() const
00199 {
00200     return strlen(addr);
00201 }
00202 
00203 
00204 sockaddr_bin *WvStringAddr::sockaddr() const
00205 {
00206     sockaddr_bin *sa = new sockaddr_bin;
00207     memset(sa, 0, sizeof(*sa));
00208     strncpy(sa->sa_data, addr, sizeof(sa->sa_data));
00209     return sa;
00210 }
00211 
00212 
00213 size_t WvStringAddr::sockaddr_len() const
00214 {
00215     return sizeof(sockaddr_bin);
00216 }
00217 
00218 
00219 WvString WvStringAddr::printable() const
00220 {
00221     return addr;
00222 }
00223 
00224 
00225 #ifndef _WIN32
00226 /* create a WvEtherAddr from a printable string in the format:
00227  *      AA:BB:CC:DD:EE:FF  (six hex numbers, separated by colons)
00228  */
00229 void WvEtherAddr::string_init(char const string[])
00230 {
00231     char *endptr = NULL;
00232     unsigned char *cptr = binaddr;
00233     
00234     memset(binaddr, 0, ETH_ALEN);
00235     for (int count=0; count < ETH_ALEN; count++)
00236     {
00237         *cptr++ = strtoul(endptr ? endptr : string, &endptr, 16);
00238         if (!endptr || endptr==string) break;
00239         endptr++;
00240     }
00241 }
00242 
00243 
00244 WvEtherAddr::~WvEtherAddr()
00245 {
00246     // nothing to do
00247 }
00248 
00249 
00250 /* Generate a printable version of an ethernet address. */
00251 WvString WvEtherAddr::printable() const
00252 {
00253     char s[ETH_ALEN*3], *cptr = s;
00254     
00255     for (int count = 0; count < ETH_ALEN; count++)
00256     {
00257         if (cptr > s)
00258             *cptr++ = ':';
00259         sprintf(cptr, "%02X", binaddr[count]);
00260         cptr += 2;
00261     }
00262     *cptr = 0;
00263 
00264     return WvString("%s", s); // create a dynamic WvString
00265 }
00266 
00267 
00268 WvEncap WvEtherAddr::encap() const
00269 {
00270     return WvEncap(WvEncap::Ethernet);
00271 }
00272 
00273 
00274 // FF:FF:FF:FF:FF:FF is the ethernet broadcast address.
00275 bool WvEtherAddr::isbroadcast() const
00276 {
00277     for (int count = 0; count < ETH_ALEN; count++)
00278         if (binaddr[count] != 0xFF)
00279             return false;
00280     return true;
00281 }
00282 
00283 
00284 const unsigned char *WvEtherAddr::rawdata() const
00285 {
00286     return binaddr;
00287 }
00288 
00289 
00290 size_t WvEtherAddr::rawdata_len() const
00291 {
00292     return ETH_ALEN;
00293 }
00294 
00295 
00296 sockaddr_bin *WvEtherAddr::sockaddr() const
00297 {
00298     sockaddr_bin *sa = new sockaddr_bin;
00299     memset(sa, 0, sizeof(*sa));
00300     sa->sa_family = ARPHRD_ETHER;
00301     memcpy(sa->sa_data, binaddr, ETH_ALEN);
00302     return sa;
00303 }
00304 
00305 
00306 size_t WvEtherAddr::sockaddr_len() const
00307 {
00308     return sizeof(sockaddr_bin);
00309 }
00310 
00311 
00312 WvARCnetAddr::~WvARCnetAddr()
00313 {
00314     // nothing to do
00315 }
00316 
00317 
00318 WvString WvARCnetAddr::printable() const
00319 {
00320     WvString s("  ");
00321     sprintf(s.edit(), "%02X", binaddr);
00322     return s;
00323 }
00324 
00325 
00326 WvEncap WvARCnetAddr::encap() const
00327 {
00328     return WvEncap(WvEncap::ARCnet);
00329 }
00330 
00331 
00332 const unsigned char *WvARCnetAddr::rawdata() const
00333 {
00334     return &binaddr;
00335 }
00336 
00337 
00338 size_t WvARCnetAddr::rawdata_len() const
00339 {
00340     return 1;
00341 }
00342 
00343 
00344 sockaddr_bin *WvARCnetAddr::sockaddr() const
00345 {
00346     sockaddr_bin *sa = new sockaddr_bin;
00347     memset(sa, 0, sizeof(*sa));
00348     sa->sa_family = ARPHRD_ARCNET;
00349     sa->sa_data[0] = binaddr;
00350     return sa;
00351 }
00352 
00353 
00354 size_t WvARCnetAddr::sockaddr_len() const
00355 {
00356     return sizeof(sockaddr_bin);
00357 }
00358 
00359 #endif //_WIN32
00360 
00361 /* create an IP address from a dotted-quad string.  Maybe someday we'll
00362  * support hostnames too with gethostbyname, but not yet.
00363  */
00364 void WvIPAddr::string_init(const char string[])
00365 {
00366     const char *iptr, *nptr;
00367     unsigned char *cptr = binaddr;
00368 
00369     memset(binaddr, 0, 4);
00370     nptr = string;
00371     for (int count=0; count < 4 && nptr; count++)
00372     {
00373         iptr = nptr;
00374         nptr = strchr(iptr, '.');
00375         if (nptr) nptr++;
00376         *cptr++ = strtol(iptr, NULL, 10);
00377         if (!nptr) break;
00378     }
00379 }
00380 
00381 WvIPAddr::~WvIPAddr()
00382 {
00383     // nothing to do
00384 }
00385 
00386 bool WvIPAddr::comparator(const WvAddr *a2, bool first_pass) const
00387 {
00388     if (a2->type() == WVIPADDR)
00389         return !memcmp(binaddr, ((WvIPAddr *)a2)->binaddr, sizeof(binaddr));
00390     else if (first_pass)
00391         return a2->comparator(this, false);
00392     else 
00393     {
00394         const unsigned char *raw1, *raw2;
00395         size_t len;
00396 
00397         len = rawdata_len();
00398         if (len != a2->rawdata_len())
00399             return false;
00400 
00401         raw1 = rawdata();
00402         raw2 = a2->rawdata();
00403 
00404         if (!raw1 && !raw2) return true;
00405         if (!raw1 || !raw2) return false;
00406 
00407         return !memcmp(raw1, raw2, len);
00408     }
00409 } 
00410 
00411 
00412 /* Generate a printable version of an IP address. */
00413 WvString WvIPAddr::printable() const
00414 {
00415     return WvString("%s.%s.%s.%s",
00416                     binaddr[0], binaddr[1], binaddr[2], binaddr[3]);
00417 }
00418 
00419 
00420 /* AND two IP addresses together (handle netmasks) */
00421 WvIPAddr WvIPAddr::operator& (const WvIPAddr &a2) const
00422 {
00423     unsigned char obin[4];
00424     
00425     for (int count=0; count<4; count++)
00426         obin[count] = binaddr[count] & a2.binaddr[count];
00427     return WvIPAddr(obin);
00428 }
00429 
00430 
00431 /* OR two IP addresses together (for broadcasts, etc) */
00432 WvIPAddr WvIPAddr::operator| (const WvIPAddr &a2) const
00433 {
00434     unsigned char obin[4];
00435     
00436     for (int count=0; count<4; count++)
00437         obin[count] = binaddr[count] | a2.binaddr[count];
00438     return WvIPAddr(obin);
00439 }
00440 
00441 
00442 /* XOR two IP addresses together (for binary operations) */
00443 WvIPAddr WvIPAddr::operator^ (const WvIPAddr &a2) const
00444 {
00445     unsigned char obin[4];
00446     
00447     for (int count=0; count<4; count++)
00448         obin[count] = binaddr[count] ^ a2.binaddr[count];
00449     return WvIPAddr(obin);
00450 }
00451 
00452 
00453 /* invert all the bits of an IP address (for useful binary operations) */
00454 WvIPAddr WvIPAddr::operator~ () const
00455 {
00456     unsigned char obin[4];
00457     
00458     for (int count=0; count<4; count++)
00459         obin[count] = ~binaddr[count];
00460     return WvIPAddr(obin);
00461 }
00462 
00463 
00464 /* add an integer value to an IP address:
00465  *   eg. 192.168.42.255 + 1 == 192.168.43.0
00466  */
00467 WvIPAddr WvIPAddr::operator+ (int n) const
00468 {
00469     __u32 newad = htonl(ntohl(addr()) + n);
00470     return WvIPAddr((unsigned char *)&newad);
00471 }
00472 
00473 
00474 WvIPAddr WvIPAddr::operator- (int n) const
00475 {
00476     __u32 newad = htonl(ntohl(addr()) - n);
00477     return WvIPAddr((unsigned char *)&newad);
00478 }
00479 
00480 
00481 WvEncap WvIPAddr::encap() const
00482 {
00483     return WvEncap(WvEncap::IPv4);
00484 }
00485 
00486 
00487 const unsigned char *WvIPAddr::rawdata() const
00488 {
00489     return binaddr;
00490 }
00491 
00492 
00493 size_t WvIPAddr::rawdata_len() const
00494 {
00495     return 4;
00496 }
00497 
00498 
00499 /* Generate a struct sockaddr (suitable for sendto()) from this IP
00500  * address.  Don't forget to delete it after you're done!
00501  */
00502 sockaddr_bin *WvIPAddr::sockaddr() const
00503 {
00504     sockaddr_in *sin = new sockaddr_in;
00505     
00506     memset(sin, 0, sizeof(*sin));
00507     sin->sin_family = AF_INET;
00508     sin->sin_addr.s_addr = addr();
00509     sin->sin_port = 0;
00510     return (sockaddr_bin *)sin;
00511 }
00512 
00513 
00514 size_t WvIPAddr::sockaddr_len() const
00515 {
00516     return sizeof(sockaddr_in);
00517 }
00518 
00519 
00520 WvIPNet::WvIPNet() { }
00521 
00522 
00523 WvIPNet::WvIPNet(const WvIPNet &_net)
00524         : WvIPAddr(_net), mask(_net.netmask()) { }
00525 
00526 
00527 // If the netmask is not specified, it will default to all 1's.
00528 void WvIPNet::string_init(const char string[])
00529 {
00530     char *maskptr;
00531     int bits;
00532     __u32 imask;
00533 
00534     maskptr = strchr(string, '/');
00535     if (!maskptr)
00536     {
00537         mask = WvIPAddr("255.255.255.255");
00538         return;
00539     }
00540     
00541     maskptr++;
00542     
00543     if (strchr(maskptr, '.'))
00544         mask = WvIPAddr(maskptr);
00545     else
00546     {
00547         bits = atoi(maskptr);
00548         if (bits > 0)
00549             imask = htonl(~(((__u32)1 << (32-bits)) - 1)); // see below
00550         else
00551             imask = 0;
00552         mask = WvIPAddr((unsigned char *)&imask);
00553     }
00554 }
00555 
00556 
00557 WvIPNet::WvIPNet(const WvIPAddr &base, const WvIPAddr &_mask)
00558         : WvIPAddr(base), mask(_mask) { }
00559 
00560 
00561 WvIPNet::WvIPNet(const WvIPAddr &base, int bits)
00562         : WvIPAddr(base)
00563 {
00564     __u32 imask;
00565     if (bits > 0) // <<32 is a bad idea!
00566         imask = htonl(~(((__u32)1 << (32-bits)) - 1));
00567     else
00568         imask = 0;
00569     mask = WvIPAddr((unsigned char *)&imask);
00570 }
00571 
00572 WvIPNet::~WvIPNet()
00573 {
00574     // nothing to do
00575 }
00576 
00577 
00578 WvString WvIPNet::printable() const
00579 {
00580     if (bits() < 32)
00581         return WvString("%s/%s", network(), bits());
00582     else
00583         return WvIPAddr::printable();
00584 }
00585 
00586 
00587 unsigned WvIPNet::WvHash() const
00588 {
00589     return WvIPAddr::WvHash() + mask.WvHash();
00590 }
00591 
00592 
00593 bool WvIPNet::comparator(const WvAddr *a2, bool first_pass) const
00594 {
00595     if (a2->type() == WVIPNET)
00596         return WvIPAddr::comparator(a2, false) && mask == ((WvIPNet *)a2)->mask;
00597     else if (first_pass)
00598         return a2->comparator(this, false);
00599     else
00600         return WvIPAddr::comparator(a2, false);
00601     
00602 }
00603 
00604 
00605 void WvIPNet::include(const WvIPNet &addr)
00606 {
00607     mask = mask & addr.mask & ~(*this ^ addr);
00608 }
00609 
00610 
00611 bool WvIPNet::includes(const WvIPNet &addr) const
00612 {
00613     return (addr.base() & netmask()) == network() &&
00614         (addr.netmask() & netmask()) == netmask();
00615 }
00616 
00617 
00618 int WvIPNet::bits() const
00619 {
00620     int bits = 0;
00621     __u32 val = ntohl(mask.addr());
00622     
00623     do
00624     {
00625         bits += val >> 31;
00626     } while ((val <<= 1) & (1 << 31));
00627     
00628     return bits;
00629 }
00630 
00631 
00632 void WvIPNet::normalize()
00633 {
00634     if (bits() > 0)
00635     {
00636         __u32 val = htonl(~(((__u32)1 << (32-bits())) - 1));
00637         mask = WvIPAddr((unsigned char *)&val);
00638     }
00639     else
00640         mask = WvIPAddr(); // empty netmask
00641 }
00642 
00643 
00644 WvIPPortAddr::WvIPPortAddr()
00645 {
00646     port = 0;
00647 }
00648 
00649 
00650 WvIPPortAddr::WvIPPortAddr(const WvIPAddr &_ipaddr, __u16 _port)
00651                         : WvIPAddr(_ipaddr)
00652 {
00653     port = _port;
00654 }
00655 
00656 
00657 // If no port is specified (after a ':' or a space or a tab) it defaults to 0.
00658 void WvIPPortAddr::string_init(const char string[]) 
00659 {
00660     struct servent* serv;
00661 
00662     const char *cptr = strchr(string, ':');
00663     if (!cptr)
00664         cptr = strchr(string, ' ');
00665     if (!cptr)
00666         cptr = strchr(string, '\t');
00667 
00668     // avoid calling getservbyname() if we can avoid it, since it's really
00669     // slow and people like to create WvIPPortAddr objects really often.
00670     if (cptr && strcmp(cptr+1, "0"))
00671     {
00672         port = atoi(cptr+1);
00673         if (!port)
00674         {
00675             serv = getservbyname(cptr+1, NULL);
00676             if (serv)
00677                 port = ntohs(serv->s_port);
00678         }
00679     }
00680     else
00681         port = 0;
00682 }
00683 
00684 
00685 WvIPPortAddr::WvIPPortAddr(__u16 _port)
00686                               : WvIPAddr("0.0.0.0")
00687 {
00688     port = _port;
00689 }
00690 
00691 
00692 WvIPPortAddr::WvIPPortAddr(const char string[], __u16 _port)
00693                               : WvIPAddr(string)
00694 {
00695     port = _port;
00696 }
00697 
00698  
00699 WvIPPortAddr::~WvIPPortAddr()
00700 {
00701     // nothing to do
00702 }
00703 
00704 
00705 /* Generate a printable version of an IP+Port Address. */
00706 WvString WvIPPortAddr::printable() const
00707 {
00708     return WvString("%s:%s", WvIPAddr::printable(), WvString(port));
00709 }
00710 
00711 
00712 /* Generate a struct sockaddr (suitable for sendto()) from this IP+Port
00713  * address.  Don't forget to delete it after you're done!
00714  */
00715 sockaddr_bin *WvIPPortAddr::sockaddr() const
00716 {
00717     sockaddr_in *sin = (sockaddr_in *)WvIPAddr::sockaddr();
00718     sin->sin_port = htons(port);
00719     return (sockaddr_bin *)sin;
00720 }
00721 
00722 
00723 unsigned WvIPPortAddr::WvHash() const
00724 {
00725     return WvIPAddr::WvHash() + port;
00726 }
00727 
00728 bool WvIPPortAddr::comparator(const WvAddr *a2, bool first_pass) const
00729 {
00730     if (a2->type() == WVIPPORTADDR)
00731         return WvIPAddr::comparator(a2, false)
00732              && port == ((WvIPPortAddr *)a2)->port;
00733     else if (first_pass)
00734         return a2->comparator(this, false);
00735     else
00736         return WvIPAddr::comparator(a2, false);
00737 
00738 }  
00739 
00740 #ifndef _WIN32
00741 WvUnixAddr::WvUnixAddr(const char *_sockname)
00742     : sockname(_sockname)
00743 {
00744     assert(!!sockname);
00745 }
00746 
00747 
00748 WvUnixAddr::WvUnixAddr(WvStringParm _sockname)
00749     : sockname(_sockname)
00750 {
00751     assert(!!sockname);
00752 }
00753 
00754 
00755 WvUnixAddr::WvUnixAddr(const WvUnixAddr &_addr)
00756     : sockname(_addr.sockname)
00757 {
00758     // nothing else needed
00759 }
00760 
00761 
00762 WvUnixAddr::~WvUnixAddr()
00763 {
00764     // nothing special
00765 }
00766 
00767 
00768 WvString WvUnixAddr::printable() const
00769 {
00770     return sockname;
00771 }
00772 
00773 
00774 WvEncap WvUnixAddr::encap() const
00775 {
00776     return WvEncap::Unix;
00777 }
00778 
00779 
00780 /* don't forget to delete the returned object when you're done! */
00781 sockaddr_bin *WvUnixAddr::sockaddr() const
00782 {
00783     sockaddr_un *sun = new sockaddr_un;
00784     
00785     memset(sun, 0, sizeof(*sun));
00786     sun->sun_family = AF_UNIX;
00787     strncpy(sun->sun_path, sockname, sizeof(sun->sun_path) - 2);
00788     return (sockaddr_bin *)sun;
00789 }
00790 
00791 
00792 size_t WvUnixAddr::sockaddr_len() const
00793 {
00794     return sizeof(sockaddr_un);
00795 }
00796 
00797 
00798 const unsigned char *WvUnixAddr::rawdata() const
00799 {
00800     return (const unsigned char *)(const char *)sockname;
00801 }
00802 
00803 
00804 size_t WvUnixAddr::rawdata_len() const
00805 {
00806     return strlen(sockname);
00807 }
00808 #endif // _WIN32

Generated on Wed Dec 15 15:08:10 2004 for WvStreams by  doxygen 1.3.9.1