1 /* 2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <NetworkRoster.h> 8 9 #include <errno.h> 10 #include <sys/sockio.h> 11 12 #include <NetworkInterface.h> 13 14 #include <net_notifications.h> 15 #include <AutoDeleter.h> 16 17 18 // TODO: using AF_INET for the socket isn't really a smart idea, as one 19 // could completely remove IPv4 support from the stack easily. 20 // Since in the stack, device_interfaces are pretty much interfaces now, we 21 // could get rid of them more or less, and make AF_LINK provide the same 22 // information as AF_INET for the interface functions mostly. 23 24 25 BNetworkRoster BNetworkRoster::sDefault; 26 27 28 /*static*/ BNetworkRoster& 29 BNetworkRoster::Default() 30 { 31 return sDefault; 32 } 33 34 35 size_t 36 BNetworkRoster::CountInterfaces() const 37 { 38 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 39 if (socket < 0) 40 return 0; 41 42 FileDescriptorCloser closer(socket); 43 44 ifconf config; 45 config.ifc_len = sizeof(config.ifc_value); 46 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) != 0) 47 return 0; 48 49 return (size_t)config.ifc_value; 50 } 51 52 53 status_t 54 BNetworkRoster::GetNextInterface(uint32* cookie, 55 BNetworkInterface& interface) const 56 { 57 // TODO: think about caching the interfaces! 58 59 if (cookie == NULL) 60 return B_BAD_VALUE; 61 62 // get a list of all interfaces 63 64 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 65 if (socket < 0) 66 return errno; 67 68 FileDescriptorCloser closer(socket); 69 70 ifconf config; 71 config.ifc_len = sizeof(config.ifc_value); 72 if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) 73 return errno; 74 75 size_t count = (size_t)config.ifc_value; 76 if (count == 0) 77 return B_BAD_VALUE; 78 79 char* buffer = (char*)malloc(count * sizeof(struct ifreq)); 80 if (buffer == NULL) 81 return B_NO_MEMORY; 82 83 MemoryDeleter deleter(buffer); 84 85 config.ifc_len = count * sizeof(struct ifreq); 86 config.ifc_buf = buffer; 87 if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) 88 return errno; 89 90 ifreq* interfaces = (ifreq*)buffer; 91 ifreq* end = (ifreq*)(buffer + config.ifc_len); 92 93 for (uint32 i = 0; interfaces < end; i++) { 94 interface.SetTo(interfaces[0].ifr_name); 95 if (i == *cookie) { 96 (*cookie)++; 97 return B_OK; 98 } 99 100 interfaces = (ifreq*)((uint8*)interfaces 101 + _SIZEOF_ADDR_IFREQ(interfaces[0])); 102 } 103 104 return B_BAD_VALUE; 105 } 106 107 108 status_t 109 BNetworkRoster::AddInterface(const BNetworkInterface& interface) 110 { 111 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 112 if (socket < 0) 113 return errno; 114 115 ifaliasreq request; 116 memset(&request, 0, sizeof(ifaliasreq)); 117 strlcpy(request.ifra_name, interface.Name(), IF_NAMESIZE); 118 119 if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) != 0) 120 return errno; 121 122 return B_OK; 123 } 124 125 126 status_t 127 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface) 128 { 129 int socket = ::socket(AF_INET, SOCK_DGRAM, 0); 130 if (socket < 0) 131 return errno; 132 133 ifreq request; 134 strlcpy(request.ifr_name, interface.Name(), IF_NAMESIZE); 135 136 request.ifr_addr.sa_family = AF_UNSPEC; 137 138 if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) != 0) 139 return errno; 140 141 return B_OK; 142 } 143 144 145 status_t 146 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask) 147 { 148 return start_watching_network(eventMask, target); 149 } 150 151 152 void 153 BNetworkRoster::StopWatching(const BMessenger& target) 154 { 155 stop_watching_network(target); 156 } 157 158 159 // #pragma mark - private 160 161 162 BNetworkRoster::BNetworkRoster() 163 { 164 } 165 166 167 BNetworkRoster::~BNetworkRoster() 168 { 169 } 170