1/* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "UnixAddress.h" 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11 12#include <util/StringHash.h> 13 14#include <net_datalink.h> 15#include <NetUtilities.h> 16 17#include "unix.h" 18 19 20static const sockaddr_un kEmptyAddress = { 21 4, // sun_len 22 AF_UNIX, // sun_family 23 { '\0', '\0' } // sun_path 24}; 25 26 27char* 28UnixAddress::ToString(char *buffer, size_t bufferSize) const 29{ 30 if (!IsValid()) 31 strlcpy(buffer, "<empty>", bufferSize); 32 else if (IsInternalAddress()) 33 snprintf(buffer, bufferSize, "<%05" B_PRIx32 ">", fInternalID); 34 else { 35 snprintf(buffer, bufferSize, "<%" B_PRIdDEV ", %" B_PRIdINO ">", 36 fVolumeID, fNodeID); 37 } 38 39 return buffer; 40} 41 42 43// #pragma mark - 44 45 46static status_t 47unix_copy_address(const sockaddr *from, sockaddr **to, bool replaceWithZeros, 48 const sockaddr *mask) 49{ 50 if (replaceWithZeros) { 51 sockaddr_un* newAddress = (sockaddr_un*)malloc(kEmptyAddress.sun_len); 52 if (newAddress == NULL) 53 return B_NO_MEMORY; 54 55 memcpy(newAddress, &kEmptyAddress, kEmptyAddress.sun_len); 56 57 *to = (sockaddr*)newAddress; 58 return B_OK; 59 } else { 60 if (from->sa_family != AF_UNIX) 61 return B_MISMATCHED_VALUES; 62 63 *to = (sockaddr*)malloc(from->sa_len); 64 if (*to == NULL) 65 return B_NO_MEMORY; 66 67 memcpy(*to, from, from->sa_len); 68 69 return B_OK; 70 } 71} 72 73 74static bool 75unix_equal_addresses(const sockaddr *a, const sockaddr *b) 76{ 77 // NOTE: We compare syntactically only. The real check would involve 78 // looking up the node, if for FS addresses. 79 if (a->sa_len != b->sa_len) 80 return false; 81 82 return memcmp(a, b, a->sa_len) == 0; 83} 84 85 86static bool 87unix_equal_ports(const sockaddr *a, const sockaddr *b) 88{ 89 // no ports 90 return true; 91} 92 93 94static bool 95unix_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b) 96{ 97 return unix_equal_addresses(a, b); 98} 99 100 101static bool 102unix_equal_masked_addresses(const sockaddr *a, const sockaddr *b, 103 const sockaddr *mask) 104{ 105 // no masks 106 return unix_equal_addresses(a, b); 107} 108 109 110static bool 111unix_is_empty_address(const sockaddr *address, bool checkPort) 112{ 113 return address == NULL || address->sa_len == 0 114 || address->sa_family == AF_UNSPEC 115 || (address->sa_len >= kEmptyAddress.sun_len 116 && memcmp(address, &kEmptyAddress, kEmptyAddress.sun_len) == 0); 117} 118 119 120static bool 121unix_is_same_family(const sockaddr *address) 122{ 123 if (address == NULL) 124 return false; 125 126 return address->sa_family == AF_UNIX; 127} 128 129 130static int32 131unix_first_mask_bit(const sockaddr *mask) 132{ 133 return 0; 134} 135 136 137static bool 138unix_check_mask(const sockaddr *address) 139{ 140 return false; 141} 142 143 144static status_t 145unix_print_address_buffer(const sockaddr *_address, char *buffer, 146 size_t bufferSize, bool printPort) 147{ 148 if (!buffer) 149 return B_BAD_VALUE; 150 151 sockaddr_un* address = (sockaddr_un*)_address; 152 153 if (address == NULL) 154 strlcpy(buffer, "<none>", bufferSize); 155 else if (address->sun_path[0] != '\0') 156 strlcpy(buffer, address->sun_path, bufferSize); 157 else if (address->sun_path[1] != '\0') 158 snprintf(buffer, bufferSize, "<%.5s>", address->sun_path + 1); 159 else 160 strlcpy(buffer, "<empty>", bufferSize); 161 162 return B_OK; 163} 164 165 166static status_t 167unix_print_address(const sockaddr *address, char **_buffer, bool printPort) 168{ 169 char buffer[128]; 170 status_t error = unix_print_address_buffer(address, buffer, sizeof(buffer), 171 printPort); 172 if (error != B_OK) 173 return error; 174 175 *_buffer = strdup(buffer); 176 return *_buffer != NULL ? B_OK : B_NO_MEMORY; 177} 178 179 180static uint16 181unix_get_port(const sockaddr *address) 182{ 183 return 0; 184} 185 186 187static status_t 188unix_set_port(sockaddr *address, uint16 port) 189{ 190 return B_BAD_VALUE; 191} 192 193 194static status_t 195unix_set_to(sockaddr *address, const sockaddr *from) 196{ 197 if (address == NULL || from == NULL) 198 return B_BAD_VALUE; 199 200 if (from->sa_family != AF_UNIX) 201 return B_MISMATCHED_VALUES; 202 203 memcpy(address, from, from->sa_len); 204 return B_OK; 205} 206 207 208static status_t 209unix_set_to_empty_address(sockaddr *address) 210{ 211 return unix_set_to(address, (sockaddr*)&kEmptyAddress); 212} 213 214 215static status_t 216unix_mask_address(const sockaddr *address, const sockaddr *mask, 217 sockaddr *result) 218{ 219 // no masks 220 return unix_set_to(result, address); 221} 222 223 224static status_t 225unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast, 226 const sockaddr *address, const sockaddr *netmask) 227{ 228 if (address == NULL) 229 return B_BAD_VALUE; 230 231 status_t error = B_OK; 232 if (defaultMask != NULL) 233 error = unix_set_to_empty_address(defaultMask); 234 if (error == B_OK && defaultBroadcast != NULL) 235 error = unix_set_to_empty_address(defaultBroadcast); 236 237 return error; 238} 239 240 241static status_t 242unix_update_to(sockaddr *address, const sockaddr *from) 243{ 244 if (address == NULL || from == NULL) 245 return B_BAD_VALUE; 246 247 if (unix_is_empty_address(from, false)) 248 return B_OK; 249 250 return unix_set_to(address, from); 251} 252 253 254static uint32 255unix_hash_address(const sockaddr* _address, bool includePort) 256{ 257 sockaddr_un* address = (sockaddr_un*)_address; 258 if (address == NULL) 259 return 0; 260 261 if (address->sun_path[0] == '\0') { 262 char buffer[6]; 263 strlcpy(buffer, address->sun_path + 1, 6); 264 return hash_hash_string(buffer); 265 } 266 267 return hash_hash_string(address->sun_path); 268} 269 270 271static uint32 272unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 273{ 274 return unix_hash_address(ourAddress, false) * 17 275 + unix_hash_address(peerAddress, false); 276} 277 278 279static status_t 280unix_checksum_address(Checksum *checksum, const sockaddr *_address) 281{ 282 if (checksum == NULL || _address == NULL) 283 return B_BAD_VALUE; 284 285 sockaddr_un* address = (sockaddr_un*)_address; 286 int len = (char*)address + address->sun_len - address->sun_path; 287 for (int i = 0; i < len; i++) 288 (*checksum) << (uint8)address->sun_path[i]; 289 290 return B_OK; 291} 292 293 294net_address_module_info gAddressModule = { 295 { 296 NULL, 297 0, 298 NULL 299 }, 300 NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS, 301 unix_copy_address, 302 unix_mask_address, 303 unix_equal_addresses, 304 unix_equal_ports, 305 unix_equal_addresses_and_ports, 306 unix_equal_masked_addresses, 307 unix_is_empty_address, 308 unix_is_same_family, 309 unix_first_mask_bit, 310 unix_check_mask, 311 unix_print_address, 312 unix_print_address_buffer, 313 unix_get_port, 314 unix_set_port, 315 unix_set_to, 316 unix_set_to_empty_address, 317 unix_set_to_defaults, 318 unix_update_to, 319 unix_hash_address, 320 unix_hash_address_pair, 321 unix_checksum_address, 322 NULL // get_loopback_address 323}; 324