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
34 const uint32 kModeAuto = 'iato';
35 const uint32 kModeStatic = 'istc';
36 const uint32 kModeDisabled = 'ioff';
37 const uint32 kMsgApply = 'aply';
38
39
40 // #pragma mark - InterfaceAddressView
41
42
InterfaceAddressView(int family,const char * interface,BNetworkSettings & settings)43 InterfaceAddressView::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
~InterfaceAddressView()118 InterfaceAddressView::~InterfaceAddressView()
119 {
120 }
121
122
123 // #pragma mark - InterfaceAddressView virtual methods
124
125
126 void
AttachedToWindow()127 InterfaceAddressView::AttachedToWindow()
128 {
129 fModePopUpMenu->SetTargetForItems(this);
130 fApplyButton->SetTarget(this);
131 }
132
133
134 void
MessageReceived(BMessage * message)135 InterfaceAddressView::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
162 status_t
Revert()163 InterfaceAddressView::Revert()
164 {
165 return fSettings.AddInterface(fOriginalSettings);
166 }
167
168
169 bool
IsRevertable() const170 InterfaceAddressView::IsRevertable() const
171 {
172 BMessage settings;
173 fSettings.GetInterface(fInterface.Name(), settings);
174
175 return !settings.HasSameData(fOriginalSettings);
176 }
177
178
179 void
ConfigurationUpdated(const BMessage & message)180 InterfaceAddressView::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
193 void
_EnableFields(bool enable)194 InterfaceAddressView::_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 */
209 void
_UpdateFields()210 InterfaceAddressView::_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
249 void
_SetModeField(uint32 mode)250 InterfaceAddressView::_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. */
270 void
_UpdateSettings()271 InterfaceAddressView::_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
304 uint32
_Mode() const305 InterfaceAddressView::_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
316 void
_ConfigureAddress(BNetworkInterfaceAddressSettings & settings)317 InterfaceAddressView::_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
339 void
_SetAddress(BNetworkAddress & address,const char * text)340 InterfaceAddressView::_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