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