Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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 Tue Oct 5 01:09:19 2004 for WvStreams by doxygen 1.3.7