1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "domains.h" 11 #include "interfaces.h" 12 13 #include <KernelExport.h> 14 15 #include <lock.h> 16 #include <util/AutoLock.h> 17 18 #include <new> 19 #include <string.h> 20 21 22 #define TRACE_DOMAINS 23 #ifdef TRACE_DOMAINS 24 # define TRACE(x) dprintf x 25 #else 26 # define TRACE(x) ; 27 #endif 28 29 static benaphore sDomainLock; 30 static list sDomains; 31 32 33 /*! 34 Scans the domain list for the specified family. 35 You need to hold the sDomainLock when calling this function. 36 */ 37 static net_domain_private * 38 lookup_domain(int family) 39 { 40 net_domain_private *domain = NULL; 41 while (true) { 42 domain = (net_domain_private *)list_get_next_item(&sDomains, domain); 43 if (domain == NULL) 44 break; 45 46 if (domain->family == family) 47 return domain; 48 } 49 50 return NULL; 51 } 52 53 54 // #pragma mark - 55 56 57 /*! 58 Gets the domain of the specified family. 59 */ 60 net_domain * 61 get_domain(int family) 62 { 63 BenaphoreLocker locker(sDomainLock); 64 return lookup_domain(family); 65 } 66 67 68 uint32 69 count_domain_interfaces() 70 { 71 BenaphoreLocker locker(sDomainLock); 72 73 net_domain_private *domain = NULL; 74 uint32 count = 0; 75 76 while (true) { 77 domain = (net_domain_private *)list_get_next_item(&sDomains, domain); 78 if (domain == NULL) 79 break; 80 81 net_interface *interface = NULL; 82 while (true) { 83 interface = (net_interface *)list_get_next_item(&domain->interfaces, 84 interface); 85 if (interface == NULL) 86 break; 87 88 count++; 89 } 90 } 91 92 return count; 93 } 94 95 96 /*! 97 Dumps a list of all interfaces into the supplied userland buffer. 98 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 99 returned. 100 */ 101 status_t 102 list_domain_interfaces(void *buffer, size_t size) 103 { 104 BenaphoreLocker locker(sDomainLock); 105 106 net_domain_private *domain = NULL; 107 size_t spaceLeft = size; 108 109 while (true) { 110 domain = (net_domain_private *)list_get_next_item(&sDomains, domain); 111 if (domain == NULL) 112 break; 113 114 net_interface *interface = NULL; 115 while (true) { 116 interface = (net_interface *)list_get_next_item(&domain->interfaces, 117 interface); 118 if (interface == NULL) 119 break; 120 121 size = IF_NAMESIZE + (interface->address ? interface->address->sa_len : 1); 122 if (spaceLeft < size) 123 return ENOBUFS; 124 125 ifreq request; 126 strlcpy(request.ifr_name, interface->name, IF_NAMESIZE); 127 if (interface->address != NULL) 128 memcpy(&request.ifr_addr, interface->address, interface->address->sa_len); 129 else { 130 // empty address 131 request.ifr_addr.sa_len = 2; 132 request.ifr_addr.sa_family = AF_UNSPEC; 133 } 134 135 if (user_memcpy(buffer, &request, size) < B_OK) 136 return B_BAD_ADDRESS; 137 138 buffer = (void *)((addr_t)buffer + size); 139 spaceLeft -= size; 140 } 141 } 142 143 return B_OK; 144 } 145 146 147 status_t 148 add_interface_to_domain(net_domain *_domain, 149 struct ifreq& request) 150 { 151 net_domain_private *domain = (net_domain_private *)_domain; 152 153 const char *deviceName = request.ifr_parameter.device[0] 154 ? request.ifr_parameter.device : request.ifr_name; 155 net_device_interface *deviceInterface = get_device_interface(deviceName); 156 if (deviceInterface == NULL) 157 return ENODEV; 158 159 BenaphoreLocker locker(domain->lock); 160 161 if (find_interface(domain, request.ifr_name) != NULL) 162 return B_NAME_IN_USE; 163 164 net_interface_private *interface; 165 status_t status = create_interface(domain, 166 request.ifr_name, request.ifr_parameter.base_name[0] 167 ? request.ifr_parameter.base_name : request.ifr_name, 168 deviceInterface, &interface); 169 if (status < B_OK) { 170 put_device_interface(deviceInterface); 171 return status; 172 } 173 174 list_add_item(&domain->interfaces, interface); 175 return B_OK; 176 } 177 178 179 /*! 180 Removes the interface from its domain, and deletes it. 181 You need to hold the domain's lock when calling this function. 182 */ 183 status_t 184 remove_interface_from_domain(net_interface *interface) 185 { 186 net_domain_private *domain = (net_domain_private *)interface->domain; 187 188 list_remove_item(&domain->interfaces, interface); 189 delete_interface((net_interface_private *)interface); 190 return B_OK; 191 } 192 193 194 status_t 195 register_domain(int family, const char *name, 196 struct net_protocol_module_info *module, 197 struct net_address_module_info *addressModule, 198 net_domain **_domain) 199 { 200 TRACE(("register_domain(%d, %s)\n", family, name)); 201 BenaphoreLocker locker(sDomainLock); 202 203 struct net_domain_private *domain = lookup_domain(family); 204 if (domain != NULL) 205 return B_NAME_IN_USE; 206 207 domain = new (std::nothrow) net_domain_private; 208 if (domain == NULL) 209 return B_NO_MEMORY; 210 211 status_t status = benaphore_init(&domain->lock, name); 212 if (status < B_OK) { 213 delete domain; 214 return status; 215 } 216 217 domain->family = family; 218 domain->name = name; 219 domain->module = module; 220 domain->address_module = addressModule; 221 222 list_init(&domain->interfaces); 223 224 list_add_item(&sDomains, domain); 225 226 *_domain = domain; 227 return B_OK; 228 } 229 230 231 status_t 232 unregister_domain(net_domain *_domain) 233 { 234 TRACE(("unregister_domain(%p, %d, %s)\n", _domain, _domain->family, _domain->name)); 235 236 net_domain_private *domain = (net_domain_private *)_domain; 237 BenaphoreLocker locker(sDomainLock); 238 239 list_remove_item(&sDomains, domain); 240 241 net_interface_private *interface = NULL; 242 while (true) { 243 interface = (net_interface_private *)list_remove_head_item(&domain->interfaces); 244 if (interface == NULL) 245 break; 246 247 delete_interface(interface); 248 } 249 250 benaphore_destroy(&domain->lock); 251 delete domain; 252 return B_OK; 253 } 254 255 256 status_t 257 init_domains() 258 { 259 if (benaphore_init(&sDomainLock, "net domains") < B_OK) 260 return B_ERROR; 261 262 list_init_etc(&sDomains, offsetof(struct net_domain_private, link)); 263 return B_OK; 264 } 265 266 267 status_t 268 uninit_domains() 269 { 270 benaphore_destroy(&sDomainLock); 271 return B_OK; 272 } 273 274