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