Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

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

Generated on Fri Apr 5 15:16:51 2002 for WvStreams by doxygen1.2.15