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 116 static int32 117 unix_first_mask_bit(const sockaddr *mask) 118 { 119 return 0; 120 } 121 122 123 static bool 124 unix_check_mask(const sockaddr *address) 125 { 126 return false; 127 } 128 129 130 static status_t 131 unix_print_address_buffer(const sockaddr *_address, char *buffer, 132 size_t bufferSize, bool printPort) 133 { 134 if (!buffer) 135 return B_BAD_VALUE; 136 137 sockaddr_un* address = (sockaddr_un*)_address; 138 139 if (address == NULL) 140 strlcpy(buffer, "<none>", bufferSize); 141 else if (address->sun_path[0] != '\0') 142 strlcpy(buffer, address->sun_path, bufferSize); 143 else if (address->sun_path[1] != '\0') 144 snprintf(buffer, bufferSize, "<%.5s>", address->sun_path + 1); 145 else 146 strlcpy(buffer, "<empty>", bufferSize); 147 148 return B_OK; 149 } 150 151 152 static status_t 153 unix_print_address(const sockaddr *address, char **_buffer, bool printPort) 154 { 155 char buffer[128]; 156 status_t error = unix_print_address_buffer(address, buffer, sizeof(buffer), 157 printPort); 158 if (error != B_OK) 159 return error; 160 161 *_buffer = strdup(buffer); 162 return *_buffer != NULL ? B_OK : B_NO_MEMORY; 163 } 164 165 166 static uint16 167 unix_get_port(const sockaddr *address) 168 { 169 return 0; 170 } 171 172 173 static status_t 174 unix_set_port(sockaddr *address, uint16 port) 175 { 176 return B_BAD_VALUE; 177 } 178 179 180 static status_t 181 unix_set_to(sockaddr *address, const sockaddr *from) 182 { 183 if (address == NULL || from == NULL) 184 return B_BAD_VALUE; 185 186 if (from->sa_family != AF_UNIX) 187 return B_MISMATCHED_VALUES; 188 189 memcpy(address, from, from->sa_len); 190 return B_OK; 191 } 192 193 194 static status_t 195 unix_set_to_empty_address(sockaddr *address) 196 { 197 return unix_set_to(address, (sockaddr*)&kEmptyAddress); 198 } 199 200 201 static status_t 202 unix_mask_address(const sockaddr *address, const sockaddr *mask, 203 sockaddr *result) 204 { 205 // no masks 206 return unix_set_to(result, address); 207 } 208 209 210 static status_t 211 unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast, 212 sockaddr *address, sockaddr *netmask) 213 { 214 if (address == NULL) 215 return B_BAD_VALUE; 216 217 status_t error = B_OK; 218 if (defaultMask != NULL) 219 error = unix_set_to_empty_address(defaultMask); 220 if (error == B_OK && defaultBroadcast != NULL) 221 error = unix_set_to_empty_address(defaultBroadcast); 222 223 return error; 224 } 225 226 227 static status_t 228 unix_update_to(sockaddr *address, const sockaddr *from) 229 { 230 if (address == NULL || from == NULL) 231 return B_BAD_VALUE; 232 233 if (unix_is_empty_address(from, false)) 234 return B_OK; 235 236 return unix_set_to(address, from); 237 } 238 239 240 static uint32 241 hash_address(const sockaddr_un* address) 242 { 243 if (address == NULL) 244 return 0; 245 246 if (address->sun_path[0] == '\0') { 247 char buffer[6]; 248 strlcpy(buffer, address->sun_path + 1, 6); 249 return hash_hash_string(buffer); 250 } 251 252 return hash_hash_string(address->sun_path); 253 } 254 255 256 static uint32 257 unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress) 258 { 259 return hash_address((sockaddr_un*)ourAddress) * 17 260 + hash_address((sockaddr_un*)peerAddress); 261 } 262 263 264 static status_t 265 unix_checksum_address(struct Checksum *checksum, const sockaddr *_address) 266 { 267 if (checksum == NULL || _address == NULL) 268 return B_BAD_VALUE; 269 270 sockaddr_un* address = (sockaddr_un*)_address; 271 int len = (char*)address + address->sun_len - address->sun_path; 272 for (int i = 0; i < len; i++) 273 (*checksum) << (uint8)address->sun_path[i]; 274 275 return B_OK; 276 } 277 278 279 net_address_module_info gAddressModule = { 280 { 281 NULL, 282 0, 283 NULL 284 }, 285 286 unix_copy_address, 287 unix_mask_address, 288 unix_equal_addresses, 289 unix_equal_ports, 290 unix_equal_addresses_and_ports, 291 unix_equal_masked_addresses, 292 unix_is_empty_address, 293 unix_first_mask_bit, 294 unix_check_mask, 295 unix_print_address, 296 unix_print_address_buffer, 297 unix_get_port, 298 unix_set_port, 299 unix_set_to, 300 unix_set_to_empty_address, 301 unix_set_to_defaults, 302 unix_update_to, 303 unix_hash_address_pair, 304 unix_checksum_address, 305 NULL // matches_broadcast_address 306 }; 307