Author: axeld Date: 2010-12-10 00:44:36 +0100 (Fri, 10 Dec 2010) New Revision: 39794 Changeset: http://dev.haiku-os.org/changeset/39794 Modified: haiku/trunk/src/servers/net/Jamfile haiku/trunk/src/servers/net/NetServer.cpp haiku/trunk/src/servers/net/Settings.cpp Log: * Added some authentication config stuff to the settings. Now you can override the detected defaults with your own values. * Implemented joining open and WEP networks - this is pretty much untested, though. Modified: haiku/trunk/src/servers/net/Jamfile =================================================================== --- haiku/trunk/src/servers/net/Jamfile 2010-12-09 23:42:19 UTC (rev 39793) +++ haiku/trunk/src/servers/net/Jamfile 2010-12-09 23:44:36 UTC (rev 39794) @@ -1,7 +1,11 @@ SubDir HAIKU_TOP src servers net ; -UsePrivateHeaders app net storage ; +UsePrivateHeaders app net shared storage ; +UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] + : true ; +UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ; + #UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libppp headers ] ; #UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ; #UseHeaders [ FDirName $(HAIKU_TOP) src tests kits net DialUpPreflet ] ; Modified: haiku/trunk/src/servers/net/NetServer.cpp =================================================================== --- haiku/trunk/src/servers/net/NetServer.cpp 2010-12-09 23:42:19 UTC (rev 39793) +++ haiku/trunk/src/servers/net/NetServer.cpp 2010-12-09 23:44:36 UTC (rev 39794) @@ -29,6 +29,7 @@ #include <Deskbar.h> #include <Directory.h> #include <Entry.h> +#include <NetworkDevice.h> #include <NetworkInterface.h> #include <NetworkRoster.h> #include <Path.h> @@ -38,11 +39,17 @@ #include <TextView.h> #include <FindDirectory.h> +#include <AutoDeleter.h> + #include "AutoconfigLooper.h" #include "Services.h" #include "Settings.h" +extern "C" { +# include <net80211/ieee80211_ioctl.h> +} + typedef std::map<std::string, AutoconfigLooper*> LooperMap; @@ -108,6 +115,52 @@ }; +// #pragma mark - private functions + + +static status_t +set_80211(const char* name, int32 type, void* data, + int32 length = 0, int32 value = 0) +{ + int socket = ::socket(AF_INET, SOCK_DGRAM, 0); + if (socket < 0) + return errno; + + FileDescriptorCloser closer(socket); + + struct ieee80211req ireq; + strlcpy(ireq.i_name, name, IF_NAMESIZE); + ireq.i_type = type; + ireq.i_val = value; + ireq.i_len = length; + ireq.i_data = data; + + if (ioctl(socket, SIOCS80211, &ireq, sizeof(struct ieee80211req)) < 0) + return errno; + + return B_OK; +} + + +static int32 +translate_wep_key(const char*& buffer, char* key) +{ + memset(key, 0, IEEE80211_KEYBUF_SIZE); + + // TODO: support possibility to set them all + if (buffer[0] != '\0') { + int32 length = strlcpy(key, buffer, IEEE80211_KEYBUF_SIZE); + buffer += length; + return length; + } + + return 0; +} + + +// #pragma mark - exported functions + + int get_address_family(const char* argument) { @@ -766,6 +819,10 @@ status_t NetServer::_JoinNetwork(const BMessage& message, const char* name) { + const char* deviceName; + if (message.FindString("device", &deviceName) != B_OK) + return B_BAD_VALUE; + BNetworkAddress address; message.FindFlat("address", &address); @@ -781,10 +838,10 @@ bool found = false; uint32 cookie = 0; - BMessage network; - while (fSettings.GetNextNetwork(cookie, network) == B_OK) { + BMessage networkMessage; + while (fSettings.GetNextNetwork(cookie, networkMessage) == B_OK) { const char* networkName; - if (network.FindString("name", &networkName) == B_OK + if (networkMessage.FindString("name", &networkName) == B_OK && name != NULL && address.Family() != AF_LINK && !strcmp(name, networkName)) { found = true; @@ -792,7 +849,7 @@ } const char* mac; - if (network.FindString("mac", &mac) == B_OK + if (networkMessage.FindString("mac", &mac) == B_OK && address.Family() == AF_LINK) { BNetworkAddress link(AF_LINK, mac); if (link == address) { @@ -804,10 +861,101 @@ const char* password; if (message.FindString("password", &password) != B_OK && found) - password = network.FindString("password"); + password = networkMessage.FindString("password"); + // Get network + BNetworkDevice device(deviceName); + wireless_network network; + if ((address.Family() != AF_LINK + || device.GetNetwork(address, network) != B_OK) + && device.GetNetwork(name, network) != B_OK) { + // We did not find a network - just ignore that, and continue + // with some defaults + strlcpy(network.name, name, sizeof(network.name)); + network.address = address; + network.authentication_mode = B_NETWORK_AUTHENTICATION_NONE; + network.cipher = 0; + network.group_cipher = 0; + network.key_mode = 0; + } + + const char* string; + if (message.FindString("authentication", &string) == B_OK + || (found && networkMessage.FindString("authentication", &string) + == B_OK)) { + if (!strcasecmp(string, "wpa2")) { + network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA2; + network.key_mode = B_KEY_MODE_IEEE802_1X; + network.cipher = network.group_cipher = B_NETWORK_CIPHER_CCMP; + } else if (!strcasecmp(string, "wpa")) { + network.authentication_mode = B_NETWORK_AUTHENTICATION_WPA; + network.key_mode = B_KEY_MODE_IEEE802_1X; + network.cipher = network.group_cipher = B_NETWORK_CIPHER_TKIP; + } else if (!strcasecmp(string, "wep")) { + network.authentication_mode = B_NETWORK_AUTHENTICATION_WEP; + network.key_mode = B_KEY_MODE_NONE; + network.cipher = network.group_cipher = B_NETWORK_CIPHER_WEP_40; + } else if (strcasecmp(string, "none") && strcasecmp(string, "open")) + fprintf(stderr, "%s: invalid authentication mode.\n", name); + } + // TODO: if password is still NULL, ask password manager once we have one - // TODO: join for real! + // TODO: remove the clear text settings password once we have + + if (password == NULL + && network.authentication_mode > B_NETWORK_AUTHENTICATION_NONE) + return B_NOT_ALLOWED; + + // Join the specified network with the specified authentication method + + if (network.authentication_mode < B_NETWORK_AUTHENTICATION_WPA) { + // we join the network ourselves + status_t status = set_80211(deviceName, IEEE80211_IOC_SSID, + network.name, strlen(network.name)); + if (status != B_OK) { + fprintf(stderr, "%s: joining SSID failed: %s\n", name, + strerror(status)); + return status; + } + + if (network.authentication_mode == B_NETWORK_AUTHENTICATION_WEP) { + status = set_80211(deviceName, IEEE80211_IOC_WEP, NULL, 0, + IEEE80211_WEP_ON); + if (status != B_OK) { + fprintf(stderr, "%s: turning on WEP failed: %s\n", name, + strerror(status)); + return status; + } + + const char* buffer = password; + + // set key + for (int32 i = 0; i < 4; i++) { + char key[IEEE80211_KEYBUF_SIZE]; + int32 keyLength = translate_wep_key(buffer, key); + status = set_80211(deviceName, IEEE80211_IOC_WEPKEY, key, + keyLength); + if (status != B_OK) + break; + } + + if (status == B_OK) { + status = set_80211(deviceName, IEEE80211_IOC_WEPKEY, NULL, 0, + 0); + } + + if (status != B_OK) { + fprintf(stderr, "%s: setting WEP keys failed: %s\n", name, + strerror(status)); + return status; + } + } + + return B_OK; + } + + // TODO: join via wpa_supplicant + return B_ERROR; } Modified: haiku/trunk/src/servers/net/Settings.cpp =================================================================== --- haiku/trunk/src/servers/net/Settings.cpp 2010-12-09 23:42:19 UTC (rev 39793) +++ haiku/trunk/src/servers/net/Settings.cpp 2010-12-09 23:44:36 UTC (rev 39794) @@ -55,7 +55,9 @@ {B_STRING_TYPE, "name", NULL, true}, {B_STRING_TYPE, "mac", NULL}, {B_STRING_TYPE, "password", NULL}, - // TODO: possibility to specify encryption modes + {B_STRING_TYPE, "authentication", NULL}, + {B_STRING_TYPE, "cipher", NULL}, + {B_STRING_TYPE, "key", NULL}, {0, NULL, NULL} };