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