Ticket #8316: ipv6localLink.diff
File ipv6localLink.diff, 10.9 KB (added by , 12 years ago) |
---|
-
src/servers/net/AutoconfigLooper.cpp
diff --git a/src/servers/net/AutoconfigLooper.cpp b/src/servers/net/AutoconfigLooper.cpp index 5e6eb03..fa162a5 100644
a b 1 1 /* 2 * Copyright 2006-201 0, Haiku, Inc. All Rights Reserved.2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved. 3 3 * Distributed under the terms of the MIT License. 4 4 * 5 5 * Authors: 6 6 * Axel Dörfler, axeld@pinc-software.de 7 * Alexander von Gluck, kallisti5@unixzen.com 7 8 */ 8 9 9 10 … … AutoconfigLooper::AutoconfigLooper(BMessenger target, const char* device) 34 35 fCurrentClient(NULL) 35 36 { 36 37 memset(fCurrentMac, 0, sizeof(fCurrentMac)); 38 37 39 BMessage ready(kMsgReadyToRun); 38 40 PostMessage(&ready); 39 41 } … … void 60 62 AutoconfigLooper::_ConfigureIPv4() 61 63 { 62 64 // start with DHCP 63 65 64 66 if (fCurrentClient == NULL) { 65 67 fCurrentClient = new DHCPClient(fTarget, fDevice.String()); 66 68 AddHandler(fCurrentClient); 67 69 } 68 70 69 71 // set IFF_CONFIGURING flag on interface 70 72 71 73 BNetworkInterface interface(fDevice.String()); … … AutoconfigLooper::_ConfigureIPv4() 120 122 } 121 123 122 124 123 #ifdef INET6124 static in6_addr125 BuildIPv6LinkLocalAddress(uint8 mac[6])126 {127 in6_addr result;128 129 result.s6_addr[0] = 0xfe;130 result.s6_addr[1] = 0x80;131 result.s6_addr[2] = 0;132 result.s6_addr[3] = 0;133 result.s6_addr[4] = 0;134 result.s6_addr[5] = 0;135 result.s6_addr[6] = 0;136 result.s6_addr[7] = 0;137 138 result.s6_addr[8] = mac[0] ^ 0x02;139 result.s6_addr[9] = mac[1];140 result.s6_addr[10] = mac[2];141 result.s6_addr[11] = 0xff;142 result.s6_addr[12] = 0xfe;143 result.s6_addr[13] = mac[3];144 result.s6_addr[14] = mac[4];145 result.s6_addr[15] = mac[5];146 147 return result;148 }149 150 151 void152 AutoconfigLooper::_ConfigureIPv6LinkLocal(bool add)153 {154 // do not touch the loopback device155 if (!strncmp(fDevice.String(), "loop", 4))156 return;157 158 ifreq request;159 if (!prepare_request(request, fDevice.String()))160 return;161 162 int socket = ::socket(AF_INET6, SOCK_DGRAM, 0);163 if (socket < 0)164 return;165 166 // set IFF_CONFIGURING flag on interface167 if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) {168 request.ifr_flags |= IFF_CONFIGURING;169 ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq));170 }171 172 uint8 mac[6];173 memcpy(mac, fCurrentMac, 6);174 if (add == true) {175 if (get_mac_address(fDevice.String(), mac) != B_OK)176 add = false;177 }178 179 if (add == true) {180 in6_addr inetAddress = BuildIPv6LinkLocalAddress(mac);181 if (_AddIPv6LinkLocal(socket, inetAddress) != true)182 add = false;183 184 // save the MAC address for later usage185 memcpy(fCurrentMac, mac, 6);186 }187 188 if (add == false) {189 static const uint8 zeroMac[6] = {0};190 if (memcmp(fCurrentMac, zeroMac, 6)) {191 in6_addr inetAddress = BuildIPv6LinkLocalAddress(fCurrentMac);192 _RemoveIPv6LinkLocal(socket, inetAddress);193 // reset the stored MAC address194 memcpy(fCurrentMac, zeroMac, 6);195 }196 }197 198 if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0199 && (request.ifr_flags & IFF_CONFIGURING) == 0) {200 // Someone else configured the interface in the mean time201 close(socket);202 return;203 }204 205 close(socket);206 }207 208 209 bool210 AutoconfigLooper::_AddIPv6LinkLocal(int socket, const in6_addr &address)211 {212 struct ifreq request;213 if (!prepare_request(request, fDevice.String()))214 return false;215 216 ifaliasreq aliasRequest;217 memset(&aliasRequest, 0, sizeof(ifaliasreq));218 strlcpy(aliasRequest.ifra_name, fDevice.String(), IF_NAMESIZE);219 aliasRequest.ifra_addr.ss_len = sizeof(sockaddr_in6);220 aliasRequest.ifra_addr.ss_family = AF_INET6;221 222 if (ioctl(socket, SIOCAIFADDR, &aliasRequest, sizeof(ifaliasreq)) < 0) {223 if (errno != B_NAME_IN_USE)224 return false;225 }226 227 sockaddr_in6* socketAddress = (sockaddr_in6*)&request.ifr_addr;228 socketAddress->sin6_len = sizeof(sockaddr_in6);229 socketAddress->sin6_family = AF_INET6;230 231 // address232 memcpy(&socketAddress->sin6_addr, &address, sizeof(in6_addr));233 if (ioctl(socket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0)234 return false;235 236 // mask (/64)237 memset(socketAddress->sin6_addr.s6_addr, 0xff, 8);238 memset(socketAddress->sin6_addr.s6_addr + 8, 0, 8);239 240 if (ioctl(socket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0)241 return false;242 243 return true;244 }245 246 247 void248 AutoconfigLooper::_RemoveIPv6LinkLocal(int socket, const in6_addr &address)249 {250 struct ifreq request;251 if (!prepare_request(request, fDevice.String()))252 return;253 254 sockaddr_in6* socketAddress = (sockaddr_in6*)&request.ifr_addr;255 socketAddress->sin6_len = sizeof(sockaddr_in6);256 socketAddress->sin6_family = AF_INET6;257 258 // address259 memcpy(&socketAddress->sin6_addr, &address, sizeof(in6_addr));260 if (ioctl(socket, SIOCDIFADDR, &request, sizeof(struct ifreq)) < 0)261 return;262 }263 #endif // INET6264 265 266 125 void 267 126 AutoconfigLooper::_ReadyToRun() 268 127 { 269 128 start_watching_network(B_WATCH_NETWORK_LINK_CHANGES, this); 270 129 _ConfigureIPv4(); 271 #ifdef INET6 272 _ConfigureIPv6LinkLocal(true); 273 #endif 130 //_ConfigureIPv6(); // TODO: router advertisement and dhcpv6 274 131 } 275 132 276 133 … … AutoconfigLooper::MessageReceived(BMessage* message) 296 153 if ((media & IFM_ACTIVE) != 0) { 297 154 // Reconfigure the interface when we have a link again 298 155 _ConfigureIPv4(); 156 //_ConfigureIPv6(); // TODO: router advertisement and dhcpv6 299 157 } 300 #ifdef INET6301 _ConfigureIPv6LinkLocal((media & IFM_ACTIVE) != 0);302 #endif303 158 break; 304 159 305 160 default: -
src/servers/net/AutoconfigLooper.h
diff --git a/src/servers/net/AutoconfigLooper.h b/src/servers/net/AutoconfigLooper.h index 669e502..7d8f1ec 100644
a b public: 29 29 private: 30 30 void _RemoveClient(); 31 31 void _ConfigureIPv4(); 32 void _ConfigureIPv6LinkLocal(bool add);33 bool _AddIPv6LinkLocal(int socket, const in6_addr &);34 void _RemoveIPv6LinkLocal(int socket, const in6_addr &);35 32 void _ReadyToRun(); 36 33 37 34 BMessenger fTarget; 38 35 BString fDevice; 39 36 AutoconfigClient* fCurrentClient; 40 uint8fCurrentMac[6];37 char fCurrentMac[6]; 41 38 }; 42 39 43 40 #endif // AUTOCONFIG_LOOPER_H -
src/servers/net/Jamfile
diff --git a/src/servers/net/Jamfile b/src/servers/net/Jamfile index da53e5b..edf2b1e 100644
a b UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ; 10 10 #UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ; 11 11 #UseHeaders [ FDirName $(HAIKU_TOP) src tests kits net DialUpPreflet ] ; 12 12 13 #local defines = [ FDefines INET6=1 ] ;14 15 13 SubDirCcFlags $(defines) ; 16 14 SubDirC++Flags $(defines) ; 17 15 -
src/servers/net/NetServer.cpp
diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index 4714b67..f0587d1 100644
a b private: 79 79 BMessage* suggestedInterface = NULL); 80 80 void _ConfigureInterfaces( 81 81 BMessage* _missingDevice = NULL); 82 void _ConfigureIPv6LinkLocal(const char* name); 82 83 void _BringUpInterfaces(); 83 84 void _StartServices(); 84 85 status_t _HandleDeviceMonitor(BMessage* message); … … struct address_family { 105 106 }; 106 107 107 108 108 // AF_INET6 family109 #if INET6110 static bool inet6_parse_address(const char* string, sockaddr* address);111 static void inet6_set_any_address(sockaddr* address);112 static void inet6_set_port(sockaddr* address, int32 port);113 #endif114 115 109 static const address_family kFamilies[] = { 116 110 { 117 111 AF_INET, … … parse_address(int32& family, const char* argument, BNetworkAddress& address) 209 203 } 210 204 211 205 212 #if INET6 213 static bool 214 inet6_parse_address(const char* string, sockaddr* _address) 215 { 216 sockaddr_in6& address = *(sockaddr_in6*)_address; 217 218 if (inet_pton(AF_INET6, string, &address.sin6_addr) != 1) 219 return false; 220 221 address.sin6_family = AF_INET6; 222 address.sin6_len = sizeof(sockaddr_in6); 223 address.sin6_port = 0; 224 address.sin6_flowinfo = 0; 225 address.sin6_scope_id = 0; 226 227 return true; 228 } 229 230 231 void 232 inet6_set_any_address(sockaddr* _address) 206 static in6_addr 207 build_ipv6_linklocal(char mac[6]) 233 208 { 234 sockaddr_in6& address = *(sockaddr_in6*)_address; 235 memset(&address, 0, sizeof(sockaddr_in6)); 236 address.sin6_family = AF_INET6; 237 address.sin6_len = sizeof(struct sockaddr_in6); 209 // Generate a Link Local Scope address 210 // (IPv6 address based on Mac address) 211 in6_addr result; 212 213 result.s6_addr[0] = 0xfe; 214 result.s6_addr[1] = 0x80; 215 result.s6_addr[2] = 0; 216 result.s6_addr[3] = 0; 217 result.s6_addr[4] = 0; 218 result.s6_addr[5] = 0; 219 result.s6_addr[6] = 0; 220 result.s6_addr[7] = 0; 221 222 result.s6_addr[8] = mac[0] ^ 0x02; 223 result.s6_addr[9] = mac[1]; 224 result.s6_addr[10] = mac[2]; 225 result.s6_addr[11] = 0xff; 226 result.s6_addr[12] = 0xfe; 227 result.s6_addr[13] = mac[3]; 228 result.s6_addr[14] = mac[4]; 229 result.s6_addr[15] = mac[5]; 230 231 return result; 238 232 } 239 233 240 234 241 void242 inet6_set_port(sockaddr* _address, int32 port)243 {244 sockaddr_in6& address = *(sockaddr_in6*)_address;245 address.sin6_port = port;246 }247 #endif248 249 250 235 // #pragma mark - 251 236 252 237 … … NetServer::_ConfigureInterface(BMessage& message) 574 559 } 575 560 } 576 561 562 // Set up IPv6 Link Local as it is the easiest to configure 563 _ConfigureIPv6LinkLocal(name); 564 577 565 BMessage addressMessage; 578 566 for (int32 index = 0; message.FindMessage("address", index, 579 567 &addressMessage) == B_OK; index++) { … … NetServer::_ConfigureInterface(BMessage& message) 619 607 if (addressMessage.FindString("broadcast", &string) == B_OK) 620 608 parse_address(family, string, broadcast); 621 609 } 622 610 623 611 if (autoConfig) { 624 612 _QuitLooperForDevice(name); 625 613 startAutoConfig = true; … … NetServer::_BringUpInterfaces() 886 874 887 875 888 876 void 877 NetServer::_ConfigureIPv6LinkLocal(const char* name) 878 { 879 // Don't touch the loopback device 880 if (!strncmp(name, "loop", 4)) 881 return; 882 883 int socket = ::socket(AF_INET6, SOCK_DGRAM, 0); 884 if (socket < 0) { 885 // No ipv6 support, skip 886 return; 887 } 888 close(socket); 889 890 BNetworkInterface interface(name); 891 BNetworkAddress hardwareAddress; 892 status_t result = interface.GetHardwareAddress(hardwareAddress); 893 if (result != B_OK) 894 return; 895 896 char mac[6]; 897 BString macString = hardwareAddress.ToString(); 898 if (macString.Length() != 0) { 899 char* macBuffer = macString.LockBuffer(sizeof(mac)); 900 memcpy(mac, macBuffer, sizeof(mac)); 901 macString.UnlockBuffer(sizeof(mac)); 902 } 903 904 static const char zeroMac[6] = {0}; 905 if (memcmp(mac, zeroMac, 6) == 0) { 906 // Mac address is all 0's. 907 return; 908 } 909 BNetworkAddress localLinkAddress(build_ipv6_linklocal(mac), 0); 910 BNetworkAddress localLinkMask("FFFF:FFFF:FFFF:FFFF::0"); // Cough /64 911 912 BNetworkInterfaceAddress interfaceAddress; 913 interfaceAddress.SetAddress(localLinkAddress); 914 interfaceAddress.SetMask(localLinkMask); 915 916 interface.AddAddress(interfaceAddress); 917 } 918 919 920 void 889 921 NetServer::_StartServices() 890 922 { 891 923 BHandler* services = new (std::nothrow) Services(fSettings.Services()); … … NetServer::_HandleDeviceMonitor(BMessage* message) 910 942 // not a device entry, ignore 911 943 return B_NAME_NOT_FOUND; 912 944 } 913 945 914 946 if (opcode == B_ENTRY_CREATED) 915 947 _ConfigureDevice(path); 916 948 else 917 949 _RemoveInterface(path); 918 950 919 951 return B_OK; 920 952 } 921 953