1/* 2 * Copyright 2004-2015 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, kallisti5@unixzen.com 7 * John Scipione, jscipione@gmail.com 8 */ 9 10 11#include "InterfaceAddressView.h" 12 13#include <stdio.h> 14 15#include <Button.h> 16#include <Catalog.h> 17#include <ControlLook.h> 18#include <LayoutBuilder.h> 19#include <MenuItem.h> 20#include <MenuField.h> 21#include <PopUpMenu.h> 22#include <Screen.h> 23#include <Size.h> 24#include <StringView.h> 25#include <TextControl.h> 26 27#include "IPAddressControl.h" 28 29 30#undef B_TRANSLATION_CONTEXT 31#define B_TRANSLATION_CONTEXT "IntefaceAddressView" 32 33 34const uint32 kModeAuto = 'iato'; 35const uint32 kModeStatic = 'istc'; 36const uint32 kModeDisabled = 'ioff'; 37const uint32 kMsgApply = 'aply'; 38 39 40// #pragma mark - InterfaceAddressView 41 42 43InterfaceAddressView::InterfaceAddressView(int family, 44 const char* interface, BNetworkSettings& settings) 45 : 46 BGroupView(B_VERTICAL), 47 fFamily(family), 48 fInterface(interface), 49 fSettings(settings) 50{ 51 SetLayout(new BGroupLayout(B_VERTICAL)); 52 53 // Create our controls 54 fModePopUpMenu = new BPopUpMenu("modes"); 55 56 if (fFamily == AF_INET) { 57 fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("DHCP"), 58 new BMessage(kModeAuto))); 59 } 60 61 if (fFamily == AF_INET6) { 62 // Automatic can be DHCPv6 or Router Advertisements 63 fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("Automatic"), 64 new BMessage(kModeAuto))); 65 } 66 67 fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("Static"), 68 new BMessage(kModeStatic))); 69 fModePopUpMenu->AddSeparatorItem(); 70 fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("Disabled"), 71 new BMessage(kModeDisabled))); 72 73 fModeField = new BMenuField(B_TRANSLATE("Mode:"), fModePopUpMenu); 74 fModeField->SetToolTip( 75 B_TRANSLATE("The method for obtaining an IP address")); 76 77 float minimumWidth = be_control_look->DefaultItemSpacing() * 15; 78 79 fAddressField = new IPAddressControl(fFamily, B_TRANSLATE("IP address:"), 80 NULL); 81 fAddressField->SetToolTip(B_TRANSLATE("Your IP address")); 82 fAddressField->TextView()->SetExplicitMinSize( 83 BSize(minimumWidth, B_SIZE_UNSET)); 84 fAddressField->SetAllowEmpty(false); 85 fNetmaskField = new IPAddressControl(fFamily, B_TRANSLATE("Netmask:"), 86 NULL); 87 fNetmaskField->SetToolTip(B_TRANSLATE( 88 "The netmask defines your local network")); 89 fNetmaskField->TextView()->SetExplicitMinSize( 90 BSize(minimumWidth, B_SIZE_UNSET)); 91 fGatewayField = new IPAddressControl(fFamily, B_TRANSLATE("Gateway:"), 92 NULL); 93 fGatewayField->SetToolTip(B_TRANSLATE("Your gateway to the internet")); 94 fGatewayField->TextView()->SetExplicitMinSize( 95 BSize(minimumWidth, B_SIZE_UNSET)); 96 97 fApplyButton = new BButton("apply", B_TRANSLATE("Apply"), 98 new BMessage(kMsgApply)); 99 100 fSettings.GetInterface(interface, fOriginalSettings); 101 _UpdateFields(); 102 103 BLayoutBuilder::Group<>(this) 104 .AddGrid() 105 .AddMenuField(fModeField, 0, 0, B_ALIGN_RIGHT) 106 .AddTextControl(fAddressField, 0, 1, B_ALIGN_RIGHT) 107 .AddTextControl(fNetmaskField, 0, 2, B_ALIGN_RIGHT) 108 .AddTextControl(fGatewayField, 0, 3, B_ALIGN_RIGHT) 109 .End() 110 .AddGroup(B_HORIZONTAL) 111 .AddGlue() 112 .Add(fApplyButton) 113 .End() 114 .AddGlue(); 115} 116 117 118InterfaceAddressView::~InterfaceAddressView() 119{ 120} 121 122 123// #pragma mark - InterfaceAddressView virtual methods 124 125 126void 127InterfaceAddressView::AttachedToWindow() 128{ 129 fModePopUpMenu->SetTargetForItems(this); 130 fApplyButton->SetTarget(this); 131} 132 133 134void 135InterfaceAddressView::MessageReceived(BMessage* message) 136{ 137 switch (message->what) { 138 case kModeAuto: 139 case kModeStatic: 140 case kModeDisabled: 141 if (message->what == fLastMode) 142 break; 143 144 _SetModeField(message->what); 145 if (message->what != kModeStatic) 146 _UpdateSettings(); 147 break; 148 149 case kMsgApply: 150 _UpdateSettings(); 151 break; 152 153 default: 154 BView::MessageReceived(message); 155 } 156} 157 158 159// #pragma mark - InterfaceAddressView public methods 160 161 162status_t 163InterfaceAddressView::Revert() 164{ 165 return fSettings.AddInterface(fOriginalSettings); 166} 167 168 169bool 170InterfaceAddressView::IsRevertable() const 171{ 172 BMessage settings; 173 fSettings.GetInterface(fInterface.Name(), settings); 174 175 return !settings.HasSameData(fOriginalSettings); 176} 177 178 179void 180InterfaceAddressView::ConfigurationUpdated(const BMessage& message) 181{ 182 const char* interface = message.GetString("interface", NULL); 183 if (interface == NULL || strcmp(interface, fInterface.Name()) != 0) 184 return; 185 186 _UpdateFields(); 187} 188 189 190// #pragma mark - InterfaceAddressView private methods 191 192 193void 194InterfaceAddressView::_EnableFields(bool enable) 195{ 196 fAddressField->SetEnabled(enable); 197 fNetmaskField->SetEnabled(enable); 198 fGatewayField->SetEnabled(enable); 199 fApplyButton->SetEnabled(enable); 200} 201 202 203/*! Updates the UI to match the current interface configuration. 204 205 The interface settings may be consulted to determine if the 206 automatic configuration has been specified, if there was no 207 configuration yet. 208*/ 209void 210InterfaceAddressView::_UpdateFields() 211{ 212 BMessage interfaceSettings; 213 fSettings.GetInterface(fInterface.Name(), interfaceSettings); 214 215 bool autoConfigure = interfaceSettings.IsEmpty(); 216 if (!autoConfigure) { 217 BNetworkInterfaceSettings settings(interfaceSettings); 218 autoConfigure = settings.IsAutoConfigure(fFamily); 219 } 220 221 BNetworkInterfaceAddress address; 222 status_t status = B_ERROR; 223 224 int32 index = fInterface.FindFirstAddress(fFamily); 225 if (index >= 0) 226 status = fInterface.GetAddressAt(index, address); 227 if (!autoConfigure && (index < 0 || status != B_OK 228 || address.Address().IsEmpty())) { 229 _SetModeField(kModeDisabled); 230 return; 231 } 232 233 if (autoConfigure) 234 _SetModeField(kModeAuto); 235 else 236 _SetModeField(kModeStatic); 237 238 fAddressField->SetText(address.Address().ToString()); 239 fNetmaskField->SetText(address.Mask().ToString()); 240 241 BNetworkAddress gateway; 242 if (fInterface.GetDefaultGateway(fFamily, gateway) == B_OK) 243 fGatewayField->SetText(gateway.ToString()); 244 else 245 fGatewayField->SetText(NULL); 246} 247 248 249void 250InterfaceAddressView::_SetModeField(uint32 mode) 251{ 252 BMenuItem* item = fModePopUpMenu->FindItem(mode); 253 if (item != NULL) 254 item->SetMarked(true); 255 256 _EnableFields(mode == kModeStatic); 257 258 if (mode == kModeDisabled) { 259 fAddressField->SetText(NULL); 260 fNetmaskField->SetText(NULL); 261 fGatewayField->SetText(NULL); 262 } else if (mode == kModeStatic) 263 fAddressField->MakeFocus(true); 264 265 fLastMode = mode; 266} 267 268 269/*! Updates the current settings from the controls. */ 270void 271InterfaceAddressView::_UpdateSettings() 272{ 273 BMessage interface; 274 fSettings.GetInterface(fInterface.Name(), interface); 275 BNetworkInterfaceSettings settings(interface); 276 277 settings.SetName(fInterface.Name()); 278 279 // Remove previous address for family 280 281 int32 index = settings.FindFirstAddress(fFamily); 282 if (index < 0) 283 index = settings.FindFirstAddress(AF_UNSPEC); 284 if (index >= 0 && index < settings.CountAddresses()) { 285 BNetworkInterfaceAddressSettings& address = settings.AddressAt(index); 286 _ConfigureAddress(address); 287 } else { 288 BNetworkInterfaceAddressSettings address; 289 _ConfigureAddress(address); 290 settings.AddAddress(address); 291 } 292 293 interface.MakeEmpty(); 294 295 // TODO: better error reporting! 296 status_t status = settings.GetMessage(interface); 297 if (status == B_OK) 298 fSettings.AddInterface(interface); 299 else 300 fprintf(stderr, "Could not add interface: %s\n", strerror(status)); 301} 302 303 304uint32 305InterfaceAddressView::_Mode() const 306{ 307 uint32 mode = kModeAuto; 308 BMenuItem* item = fModePopUpMenu->FindMarked(); 309 if (item != NULL) 310 mode = item->Message()->what; 311 312 return mode; 313} 314 315 316void 317InterfaceAddressView::_ConfigureAddress( 318 BNetworkInterfaceAddressSettings& settings) 319{ 320 uint32 mode = _Mode(); 321 322 settings.SetFamily(fFamily); 323 settings.SetAutoConfigure(mode == kModeAuto); 324 325 settings.Address().Unset(); 326 settings.Mask().Unset(); 327 settings.Peer().Unset(); 328 settings.Broadcast().Unset(); 329 settings.Gateway().Unset(); 330 331 if (mode == kModeStatic) { 332 _SetAddress(settings.Address(), fAddressField->Text()); 333 _SetAddress(settings.Mask(), fNetmaskField->Text()); 334 _SetAddress(settings.Gateway(), fGatewayField->Text()); 335 } 336} 337 338 339void 340InterfaceAddressView::_SetAddress(BNetworkAddress& address, const char* text) 341{ 342 BString string(text); 343 string.Trim(); 344 if (string.IsEmpty()) 345 return; 346 347 address.SetTo(string.String(), static_cast<uint16>(0), 348 B_NO_ADDRESS_RESOLUTION); 349} 350