diff --git a/headers/os/net/NetworkDevice.h b/headers/os/net/NetworkDevice.h index fb97c26218..fe782be2ab 100644 --- a/headers/os/net/NetworkDevice.h +++ b/headers/os/net/NetworkDevice.h @@ -28,6 +28,7 @@ struct wireless_network { // flags #define B_NETWORK_IS_ENCRYPTED 0x01 +#define B_NETWORK_IS_PERSISTENT 0x02 // authentication modes enum { @@ -97,9 +98,6 @@ public: status_t GetNetwork(const BNetworkAddress& address, wireless_network& network); - status_t AddPersistentNetwork( - const wireless_network& network); - status_t JoinNetwork(const char* name, const char* password = NULL); status_t JoinNetwork(const wireless_network& network, diff --git a/headers/os/net/NetworkRoster.h b/headers/os/net/NetworkRoster.h index 849694542a..4d66365df9 100644 --- a/headers/os/net/NetworkRoster.h +++ b/headers/os/net/NetworkRoster.h @@ -12,6 +12,7 @@ class BMessenger; class BNetworkInterface; +struct wireless_network; class BNetworkRoster { @@ -29,6 +30,13 @@ public: status_t RemoveInterface( const BNetworkInterface& interface); + int32 CountPersistentNetworks() const; + status_t GetNextPersistentNetwork(uint32* cookie, + wireless_network& network) const; + status_t AddPersistentNetwork( + const wireless_network& network); + status_t RemovePersistentNetwork(const char* name); + status_t StartWatching(const BMessenger& target, uint32 eventMask); void StopWatching(const BMessenger& target); diff --git a/headers/private/net/NetServer.h b/headers/private/net/NetServer.h index 70b7eb0fff..9b66ad9a0f 100644 --- a/headers/private/net/NetServer.h +++ b/headers/private/net/NetServer.h @@ -13,7 +13,10 @@ #define kMsgConfigureInterface 'COif' #define kMsgConfigureResolver 'COrs' +#define kMsgCountPersistentNetworks 'CPnw' +#define kMsgGetPersistentNetwork 'GPnw' #define kMsgAddPersistentNetwork 'APnw' +#define kMsgRemovePersistentNetwork 'RPnw' #define kMsgJoinNetwork 'JNnw' #define kMsgLeaveNetwork 'LVnw' diff --git a/src/kits/network/libnetapi/NetworkDevice.cpp b/src/kits/network/libnetapi/NetworkDevice.cpp index f4ac139fdf..827ee06732 100644 --- a/src/kits/network/libnetapi/NetworkDevice.cpp +++ b/src/kits/network/libnetapi/NetworkDevice.cpp @@ -696,90 +696,6 @@ BNetworkDevice::GetNetwork(const BNetworkAddress& address, } -status_t -BNetworkDevice::AddPersistentNetwork(const wireless_network& network) -{ - BMessage message(kMsgAddPersistentNetwork); - status_t status = message.AddString("name", network.name); - if (status != B_OK) - return status; - - if (status == B_OK && network.address.Family() == AF_LINK) { - size_t addressLength = network.address.LinkLevelAddressLength(); - uint8* macAddress = network.address.LinkLevelAddress(); - bool usable = false; - BString formatted; - - for (size_t index = 0; index < addressLength; index++) { - if (index > 0) - formatted.Append(":"); - char buffer[3]; - snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]); - formatted.Append(buffer, sizeof(buffer)); - - if (macAddress[index] != 0) - usable = true; - } - - if (usable) - status = message.AddString("mac", formatted); - } - - const char* authentication = NULL; - switch (network.authentication_mode) { - case B_NETWORK_AUTHENTICATION_NONE: - authentication = "none"; - break; - case B_NETWORK_AUTHENTICATION_WEP: - authentication = "wep"; - break; - case B_NETWORK_AUTHENTICATION_WPA: - authentication = "wpa"; - break; - case B_NETWORK_AUTHENTICATION_WPA2: - authentication = "wpa2"; - break; - } - - if (status == B_OK && authentication != NULL) - status = message.AddString("authentication", authentication); - - if (status == B_OK && (network.cipher & B_NETWORK_CIPHER_NONE) != 0) - status = message.AddString("cipher", "none"); - if (status == B_OK && (network.cipher & B_NETWORK_CIPHER_TKIP) != 0) - status = message.AddString("cipher", "tkip"); - if (status == B_OK && (network.cipher & B_NETWORK_CIPHER_CCMP) != 0) - status = message.AddString("cipher", "ccmp"); - - if (status == B_OK && (network.group_cipher & B_NETWORK_CIPHER_NONE) != 0) - status = message.AddString("group_cipher", "none"); - if (status == B_OK && (network.group_cipher & B_NETWORK_CIPHER_WEP_40) != 0) - status = message.AddString("group_cipher", "wep40"); - if (status == B_OK - && (network.group_cipher & B_NETWORK_CIPHER_WEP_104) != 0) { - status = message.AddString("group_cipher", "wep104"); - } - if (status == B_OK && (network.group_cipher & B_NETWORK_CIPHER_TKIP) != 0) - status = message.AddString("group_cipher", "tkip"); - if (status == B_OK && (network.group_cipher & B_NETWORK_CIPHER_CCMP) != 0) - status = message.AddString("group_cipher", "ccmp"); - - // TODO: the other fields aren't currently used, add them when they are - // and when it's clear how they will be stored - - if (status != B_OK) - return status; - - BMessenger networkServer(kNetServerSignature); - BMessage reply; - status = networkServer.SendMessage(&message, &reply); - if (status == B_OK) - reply.FindInt32("status", &status); - - return status; -} - - status_t BNetworkDevice::JoinNetwork(const char* name, const char* password) { diff --git a/src/kits/network/libnetapi/NetworkRoster.cpp b/src/kits/network/libnetapi/NetworkRoster.cpp index 43b4975d6a..d847f5a24a 100644 --- a/src/kits/network/libnetapi/NetworkRoster.cpp +++ b/src/kits/network/libnetapi/NetworkRoster.cpp @@ -9,10 +9,12 @@ #include #include +#include #include #include #include +#include // TODO: using AF_INET for the socket isn't really a smart idea, as one @@ -156,6 +158,136 @@ BNetworkRoster::RemoveInterface(const BNetworkInterface& interface) } +int32 +BNetworkRoster::CountPersistentNetworks() const +{ + BMessenger networkServer(kNetServerSignature); + BMessage message(kMsgCountPersistentNetworks); + BMessage reply; + if (networkServer.SendMessage(&message, &reply) != B_OK) + return 0; + + int32 count = 0; + if (reply.FindInt32("count", &count) != B_OK) + return 0; + + return count; +} + + +status_t +BNetworkRoster::GetNextPersistentNetwork(uint32* cookie, + wireless_network& network) const +{ + BMessenger networkServer(kNetServerSignature); + BMessage message(kMsgGetPersistentNetwork); + message.AddInt32("index", (int32)*cookie); + + BMessage reply; + status_t result = networkServer.SendMessage(&message, &reply); + if (result != B_OK) + return result; + + status_t status; + if (reply.FindInt32("status", &status) != B_OK) + return B_ERROR; + if (status != B_OK) + return status; + + BMessage networkMessage; + if (reply.FindMessage("network", &networkMessage) != B_OK) + return B_ERROR; + + BString networkName; + if (networkMessage.FindString("name", &networkName) != B_OK) + return B_ERROR; + + memset(network.name, 0, sizeof(network.name)); + strncpy(network.name, networkName.String(), sizeof(network.name)); + + BNetworkAddress address; + if (networkMessage.FindFlat("address", &network.address) != B_OK) + network.address.Unset(); + + if (networkMessage.FindUInt32("flags", &network.flags) != B_OK) + network.flags = 0; + + if (networkMessage.FindUInt32("authentication_mode", + &network.authentication_mode) != B_OK) { + network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; + } + + if (networkMessage.FindUInt32("cipher", &network.cipher) != B_OK) + network.cipher = B_NETWORK_CIPHER_NONE; + + if (networkMessage.FindUInt32("group_cipher", &network.group_cipher) + != B_OK) { + network.group_cipher = B_NETWORK_CIPHER_NONE; + } + + if (networkMessage.FindUInt32("key_mode", &network.key_mode) != B_OK) + network.key_mode = B_KEY_MODE_NONE; + + return B_OK; +} + + +status_t +BNetworkRoster::AddPersistentNetwork(const wireless_network& network) +{ + BMessage message(kMsgAddPersistentNetwork); + BString networkName; + networkName.SetTo(network.name, sizeof(network.name)); + status_t status = message.AddString("name", networkName); + if (status == B_OK) { + BNetworkAddress address = network.address; + status = message.AddFlat("address", &address); + } + + if (status == B_OK) + status = message.AddUInt32("flags", network.flags); + if (status == B_OK) { + status = message.AddUInt32("authentication_mode", + network.authentication_mode); + } + if (status == B_OK) + status = message.AddUInt32("cipher", network.cipher); + if (status == B_OK) + status = message.AddUInt32("group_cipher", network.group_cipher); + if (status == B_OK) + status = message.AddUInt32("key_mode", network.key_mode); + + if (status != B_OK) + return status; + + BMessenger networkServer(kNetServerSignature); + BMessage reply; + status = networkServer.SendMessage(&message, &reply); + if (status == B_OK) + reply.FindInt32("status", &status); + + return status; +} + + +status_t +BNetworkRoster::RemovePersistentNetwork(const char* name) +{ + BMessage message(kMsgRemovePersistentNetwork); + status_t status = message.AddString("name", name); + if (status != B_OK) + return status; + + BMessenger networkServer(kNetServerSignature); + BMessage reply; + status = networkServer.SendMessage(&message, &reply); + if (status == B_OK) + reply.FindInt32("status", &status); + + return status; +} + + status_t BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask) { diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index 301f827c86..4714b675fd 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -88,6 +88,9 @@ private: const char* name = NULL); status_t _LeaveNetwork(const BMessage& message); + status_t _ConvertNetworkToSettings(BMessage& message); + status_t _ConvertNetworkFromSettings(BMessage& message); + private: Settings fSettings; LooperMap fDeviceMap; @@ -357,12 +360,55 @@ NetServer::MessageReceived(BMessage* message) break; } - case kMsgAddPersistentNetwork: + case kMsgCountPersistentNetworks: { - status_t status = fSettings.AddNetwork(*message); + BMessage reply(B_REPLY); + reply.AddInt32("count", fSettings.CountNetworks()); + message->SendReply(&reply); + break; + } + + case kMsgGetPersistentNetwork: + { + uint32 index = 0; + status_t result = message->FindInt32("index", (int32*)&index); BMessage reply(B_REPLY); - reply.AddInt32("status", status); + if (result == B_OK) { + BMessage network; + result = fSettings.GetNextNetwork(index, network); + if (result == B_OK) + result = _ConvertNetworkFromSettings(network); + if (result == B_OK) + result = reply.AddMessage("network", &network); + } + + reply.AddInt32("status", result); + message->SendReply(&reply); + break; + } + + case kMsgAddPersistentNetwork: + { + status_t result = _ConvertNetworkToSettings(*message); + if (result == B_OK) + result = fSettings.AddNetwork(*message); + + BMessage reply(B_REPLY); + reply.AddInt32("status", result); + message->SendReply(&reply); + break; + } + + case kMsgRemovePersistentNetwork: + { + const char* networkName = NULL; + status_t result = message->FindString("name", &networkName); + if (result == B_OK) + result = fSettings.RemoveNetwork(networkName); + + BMessage reply(B_REPLY); + reply.AddInt32("status", result); message->SendReply(&reply); break; } @@ -511,7 +557,7 @@ NetServer::_ConfigureInterface(BMessage& message) BNetworkDevice device(name); if (device.IsWireless()) { const char* networkName; - if (message.FindString("network", &networkName) != B_OK) { + if (message.FindString("network", &networkName) == B_OK) { // join configured network status_t status = _JoinNetwork(message, networkName); if (status != B_OK) { @@ -908,23 +954,7 @@ NetServer::_AutoJoinNetwork(const char* name) } } - // None found, try them all - - wireless_network network; - cookie = 0; - while (device.GetNextNetwork(cookie, network) == B_OK) { - if ((network.flags & B_NETWORK_IS_ENCRYPTED) == 0) { - status_t status = _JoinNetwork(message, network.name); - printf("auto join open network \"%s\": %s\n", network.name, - strerror(status)); - if (status == B_OK) - return status; - } - - // TODO: once we have a password manager, use that - } - - return B_ERROR; + return B_NO_INIT; } @@ -1053,12 +1083,11 @@ NetServer::_JoinNetwork(const BMessage& message, const char* name) return status; BMessenger wpaSupplicant(kWPASupplicantSignature); - BMessage reply; - status = wpaSupplicant.SendMessage(&join, &reply); + status = wpaSupplicant.SendMessage(&join); if (status != B_OK) return status; - return reply.FindInt32("status"); + return B_OK; } @@ -1070,6 +1099,169 @@ NetServer::_LeaveNetwork(const BMessage& message) } +status_t +NetServer::_ConvertNetworkToSettings(BMessage& message) +{ + BNetworkAddress address; + status_t result = message.FindFlat("address", &address); + if (result == B_OK) + message.RemoveName("address"); + + if (result == B_OK && address.Family() == AF_LINK) { + size_t addressLength = address.LinkLevelAddressLength(); + uint8* macAddress = address.LinkLevelAddress(); + bool usable = false; + BString formatted; + + for (size_t index = 0; index < addressLength; index++) { + if (index > 0) + formatted.Append(":"); + char buffer[3]; + snprintf(buffer, sizeof(buffer), "%2x", macAddress[index]); + formatted.Append(buffer, sizeof(buffer)); + + if (macAddress[index] != 0) + usable = true; + } + + if (usable) + message.AddString("mac", formatted); + } + + uint32 authentication = 0; + result = message.FindUInt32("authentication_mode", &authentication); + if (result == B_OK) { + message.RemoveName("authentication_mode"); + + const char* authenticationString = NULL; + switch (authentication) { + case B_NETWORK_AUTHENTICATION_NONE: + authenticationString = "none"; + break; + case B_NETWORK_AUTHENTICATION_WEP: + authenticationString = "wep"; + break; + case B_NETWORK_AUTHENTICATION_WPA: + authenticationString = "wpa"; + break; + case B_NETWORK_AUTHENTICATION_WPA2: + authenticationString = "wpa2"; + break; + } + + if (result == B_OK && authenticationString != NULL) + message.AddString("authentication", authenticationString); + } + + uint32 cipher = 0; + result = message.FindUInt32("cipher", &cipher); + if (result == B_OK) { + message.RemoveName("cipher"); + + if ((cipher & B_NETWORK_CIPHER_NONE) != 0) + message.AddString("cipher", "none"); + if ((cipher & B_NETWORK_CIPHER_TKIP) != 0) + message.AddString("cipher", "tkip"); + if ((cipher & B_NETWORK_CIPHER_CCMP) != 0) + message.AddString("cipher", "ccmp"); + } + + uint32 groupCipher = 0; + result = message.FindUInt32("group_cipher", &groupCipher); + if (result == B_OK) { + message.RemoveName("group_cipher"); + + if ((groupCipher & B_NETWORK_CIPHER_NONE) != 0) + message.AddString("group_cipher", "none"); + if ((groupCipher & B_NETWORK_CIPHER_WEP_40) != 0) + message.AddString("group_cipher", "wep40"); + if ((groupCipher & B_NETWORK_CIPHER_WEP_104) != 0) + message.AddString("group_cipher", "wep104"); + if ((groupCipher & B_NETWORK_CIPHER_TKIP) != 0) + message.AddString("group_cipher", "tkip"); + if ((groupCipher & B_NETWORK_CIPHER_CCMP) != 0) + message.AddString("group_cipher", "ccmp"); + } + + // TODO: the other fields aren't currently used, add them when they are + // and when it's clear how they will be stored + message.RemoveName("noise_level"); + message.RemoveName("signal_strength"); + message.RemoveName("flags"); + message.RemoveName("key_mode"); + + return B_OK; +} + + +status_t +NetServer::_ConvertNetworkFromSettings(BMessage& message) +{ + message.RemoveName("mac"); + // TODO: convert into a flat BNetworkAddress "address" + + const char* authentication = NULL; + if (message.FindString("authentication", &authentication) == B_OK) { + message.RemoveName("authentication"); + + if (strcasecmp(authentication, "none") == 0) { + message.AddUInt32("authentication_mode", + B_NETWORK_AUTHENTICATION_NONE); + } else if (strcasecmp(authentication, "wep") == 0) { + message.AddUInt32("authentication_mode", + B_NETWORK_AUTHENTICATION_WEP); + } else if (strcasecmp(authentication, "wpa") == 0) { + message.AddUInt32("authentication_mode", + B_NETWORK_AUTHENTICATION_WPA); + } else if (strcasecmp(authentication, "wpa2") == 0) { + message.AddUInt32("authentication_mode", + B_NETWORK_AUTHENTICATION_WPA2); + } + } + + int32 index = 0; + uint32 cipher = 0; + const char* cipherString = NULL; + while (message.FindString("cipher", index++, &cipherString) == B_OK) { + if (strcasecmp(cipherString, "none") == 0) + cipher |= B_NETWORK_CIPHER_NONE; + else if (strcasecmp(cipherString, "tkip") == 0) + cipher |= B_NETWORK_CIPHER_TKIP; + else if (strcasecmp(cipherString, "ccmp") == 0) + cipher |= B_NETWORK_CIPHER_CCMP; + } + + message.RemoveName("cipher"); + if (cipher != 0) + message.AddUInt32("cipher", cipher); + + index = 0; + cipher = 0; + while (message.FindString("group_cipher", index++, &cipherString) == B_OK) { + if (strcasecmp(cipherString, "none") == 0) + cipher |= B_NETWORK_CIPHER_NONE; + else if (strcasecmp(cipherString, "wep40") == 0) + cipher |= B_NETWORK_CIPHER_WEP_40; + else if (strcasecmp(cipherString, "wep104") == 0) + cipher |= B_NETWORK_CIPHER_WEP_104; + else if (strcasecmp(cipherString, "tkip") == 0) + cipher |= B_NETWORK_CIPHER_TKIP; + else if (strcasecmp(cipherString, "ccmp") == 0) + cipher |= B_NETWORK_CIPHER_CCMP; + } + + message.RemoveName("group_cipher"); + if (cipher != 0) + message.AddUInt32("group_cipher", cipher); + + message.AddUInt32("flags", B_NETWORK_IS_PERSISTENT); + + // TODO: add the other fields + message.RemoveName("key"); + return B_OK; +} + + // #pragma mark - diff --git a/src/servers/net/Settings.cpp b/src/servers/net/Settings.cpp index c164cf4dda..36dafc21c9 100644 --- a/src/servers/net/Settings.cpp +++ b/src/servers/net/Settings.cpp @@ -65,6 +65,7 @@ const static settings_template kNetworkTemplate[] = { {B_STRING_TYPE, "password", NULL}, {B_STRING_TYPE, "authentication", NULL}, {B_STRING_TYPE, "cipher", NULL}, + {B_STRING_TYPE, "group_cipher", NULL}, {B_STRING_TYPE, "key", NULL}, {0, NULL, NULL} }; @@ -412,6 +413,7 @@ Settings::_ConvertToDriverSettings(const char* name, if (status == B_OK) { settings.RemoveFirst("\n"); // TODO: actually write the settings.String() out into the file + printf("settings:\n%s\n", settings.String()); } return status; @@ -563,8 +565,19 @@ Settings::GetNextInterface(uint32& cookie, BMessage& interface) } +int32 +Settings::CountNetworks() const +{ + int32 count = 0; + if (fNetworks.GetInfo("network", NULL, &count) != B_OK) + return 0; + + return count; +} + + status_t -Settings::GetNextNetwork(uint32& cookie, BMessage& network) +Settings::GetNextNetwork(uint32& cookie, BMessage& network) const { status_t status = fNetworks.FindMessage("network", cookie, &network); if (status != B_OK) @@ -578,6 +591,10 @@ Settings::GetNextNetwork(uint32& cookie, BMessage& network) status_t Settings::AddNetwork(const BMessage& network) { + const char* name = NULL; + network.FindString("name", &name); + RemoveNetwork(name); + status_t result = fNetworks.AddMessage("network", &network); if (result != B_OK) return result; @@ -586,6 +603,26 @@ Settings::AddNetwork(const BMessage& network) } +status_t +Settings::RemoveNetwork(const char* name) +{ + int32 index = 0; + BMessage network; + while (fNetworks.FindMessage("network", index, &network) == B_OK) { + const char* networkName = NULL; + if (network.FindString("name", &networkName) == B_OK + && strcmp(networkName, name) == 0) { + fNetworks.RemoveData("network", index); + return _Save("wireless_networks"); + } + + index++; + } + + return B_ENTRY_NOT_FOUND; +} + + status_t Settings::GetNextService(uint32& cookie, BMessage& service) { diff --git a/src/servers/net/Settings.h b/src/servers/net/Settings.h index d782f1ebbd..01f2e16521 100644 --- a/src/servers/net/Settings.h +++ b/src/servers/net/Settings.h @@ -26,9 +26,11 @@ public: status_t GetNextInterface(uint32& cookie, BMessage& interface); + int32 CountNetworks() const; status_t GetNextNetwork(uint32& cookie, - BMessage& network); + BMessage& network) const; status_t AddNetwork(const BMessage& network); + status_t RemoveNetwork(const char* name); status_t GetNextService(uint32& cookie, BMessage& service);