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