Ticket #8316: ipv6localLink.diff

File ipv6localLink.diff, 10.9 KB (added by kallisti5, 12 years ago)

v1.0

  • 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  
    11/*
    2  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
     2 * Copyright 2006-2012, Haiku, Inc. All Rights Reserved.
    33 * Distributed under the terms of the MIT License.
    44 *
    55 * Authors:
    66 *      Axel Dörfler, axeld@pinc-software.de
     7 *      Alexander von Gluck, kallisti5@unixzen.com
    78 */
    89
    910
    AutoconfigLooper::AutoconfigLooper(BMessenger target, const char* device)  
    3435    fCurrentClient(NULL)
    3536{
    3637    memset(fCurrentMac, 0, sizeof(fCurrentMac));
     38
    3739    BMessage ready(kMsgReadyToRun);
    3840    PostMessage(&ready);
    3941}
    void  
    6062AutoconfigLooper::_ConfigureIPv4()
    6163{
    6264    // start with DHCP
    63    
     65
    6466    if (fCurrentClient == NULL) {
    6567        fCurrentClient = new DHCPClient(fTarget, fDevice.String());
    6668        AddHandler(fCurrentClient);
    6769    }
    68    
     70
    6971    // set IFF_CONFIGURING flag on interface
    7072
    7173    BNetworkInterface interface(fDevice.String());
    AutoconfigLooper::_ConfigureIPv4()  
    120122}
    121123
    122124
    123 #ifdef INET6
    124 static in6_addr
    125 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 void
    152 AutoconfigLooper::_ConfigureIPv6LinkLocal(bool add)
    153 {
    154     // do not touch the loopback device
    155     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 interface
    167     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 usage
    185         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 address
    194             memcpy(fCurrentMac, zeroMac, 6);
    195         }
    196     }
    197 
    198     if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0
    199         && (request.ifr_flags & IFF_CONFIGURING) == 0) {
    200         // Someone else configured the interface in the mean time
    201         close(socket);
    202         return;
    203     }
    204 
    205     close(socket);
    206 }
    207 
    208 
    209 bool
    210 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     // address
    232     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 void
    248 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     // address
    259     memcpy(&socketAddress->sin6_addr, &address, sizeof(in6_addr));
    260     if (ioctl(socket, SIOCDIFADDR, &request, sizeof(struct ifreq)) < 0)
    261         return;
    262 }
    263 #endif // INET6
    264 
    265 
    266125void
    267126AutoconfigLooper::_ReadyToRun()
    268127{
    269128    start_watching_network(B_WATCH_NETWORK_LINK_CHANGES, this);
    270129    _ConfigureIPv4();
    271 #ifdef INET6
    272     _ConfigureIPv6LinkLocal(true);
    273 #endif
     130    //_ConfigureIPv6(); // TODO: router advertisement and dhcpv6
    274131}
    275132
    276133
    AutoconfigLooper::MessageReceived(BMessage* message)  
    296153            if ((media & IFM_ACTIVE) != 0) {
    297154                // Reconfigure the interface when we have a link again
    298155                _ConfigureIPv4();
     156                //_ConfigureIPv6(); // TODO: router advertisement and dhcpv6
    299157            }
    300 #ifdef INET6
    301             _ConfigureIPv6LinkLocal((media & IFM_ACTIVE) != 0);
    302 #endif
    303158            break;
    304159
    305160        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:  
    2929private:
    3030            void                _RemoveClient();
    3131            void                _ConfigureIPv4();
    32             void                _ConfigureIPv6LinkLocal(bool add);
    33             bool                _AddIPv6LinkLocal(int socket, const in6_addr &);
    34             void                _RemoveIPv6LinkLocal(int socket, const in6_addr &);
    3532            void                _ReadyToRun();
    3633
    3734            BMessenger          fTarget;
    3835            BString             fDevice;
    3936            AutoconfigClient*   fCurrentClient;
    40             uint8               fCurrentMac[6];
     37            char                fCurrentMac[6];
    4138};
    4239
    4340#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 ;  
    1010#UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ;
    1111#UseHeaders [ FDirName $(HAIKU_TOP) src tests kits net DialUpPreflet ] ;
    1212
    13 #local defines = [ FDefines INET6=1 ] ;
    14 
    1513SubDirCcFlags $(defines) ;
    1614SubDirC++Flags $(defines) ;
    1715
  • 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:  
    7979                                    BMessage* suggestedInterface = NULL);
    8080            void                _ConfigureInterfaces(
    8181                                    BMessage* _missingDevice = NULL);
     82            void                _ConfigureIPv6LinkLocal(const char* name);
    8283            void                _BringUpInterfaces();
    8384            void                _StartServices();
    8485            status_t            _HandleDeviceMonitor(BMessage* message);
    struct address_family {  
    105106};
    106107
    107108
    108 // AF_INET6 family
    109 #if INET6
    110 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 #endif
    114 
    115109static const address_family kFamilies[] = {
    116110    {
    117111        AF_INET,
    parse_address(int32& family, const char* argument, BNetworkAddress& address)  
    209203}
    210204
    211205
    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)
     206static in6_addr
     207build_ipv6_linklocal(char mac[6])
    233208{
    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;
    238232}
    239233
    240234
    241 void
    242 inet6_set_port(sockaddr* _address, int32 port)
    243 {
    244     sockaddr_in6& address = *(sockaddr_in6*)_address;
    245     address.sin6_port = port;
    246 }
    247 #endif
    248 
    249 
    250235//  #pragma mark -
    251236
    252237
    NetServer::_ConfigureInterface(BMessage& message)  
    574559        }
    575560    }
    576561
     562    // Set up IPv6 Link Local as it is the easiest to configure
     563    _ConfigureIPv6LinkLocal(name);
     564
    577565    BMessage addressMessage;
    578566    for (int32 index = 0; message.FindMessage("address", index,
    579567            &addressMessage) == B_OK; index++) {
    NetServer::_ConfigureInterface(BMessage& message)  
    619607            if (addressMessage.FindString("broadcast", &string) == B_OK)
    620608                parse_address(family, string, broadcast);
    621609        }
    622        
     610
    623611        if (autoConfig) {
    624612            _QuitLooperForDevice(name);
    625613            startAutoConfig = true;
    NetServer::_BringUpInterfaces()  
    886874
    887875
    888876void
     877NetServer::_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
     920void
    889921NetServer::_StartServices()
    890922{
    891923    BHandler* services = new (std::nothrow) Services(fSettings.Services());
    NetServer::_HandleDeviceMonitor(BMessage* message)  
    910942        // not a device entry, ignore
    911943        return B_NAME_NOT_FOUND;
    912944    }
    913            
     945
    914946    if (opcode == B_ENTRY_CREATED)
    915947        _ConfigureDevice(path);
    916948    else
    917949        _RemoveInterface(path);
    918        
     950
    919951    return B_OK;
    920952}
    921953