1a4a34e42SAxel Dörfler /*
29a7e231eSAxel Dörfler * Copyright 2014-2015 Haiku Inc. All rights reserved.
3a4a34e42SAxel Dörfler * Distributed under the terms of the MIT License.
4a4a34e42SAxel Dörfler *
5a4a34e42SAxel Dörfler * Authors:
6a4a34e42SAxel Dörfler * Adrien Destugues, pulkomandy@pulkomandy.tk
7a4a34e42SAxel Dörfler */
8a4a34e42SAxel Dörfler
9a4a34e42SAxel Dörfler
10a4a34e42SAxel Dörfler #include "DNSSettingsView.h"
11a4a34e42SAxel Dörfler
129a7e231eSAxel Dörfler #include <arpa/inet.h>
139a7e231eSAxel Dörfler #include <netinet/in.h>
149a7e231eSAxel Dörfler #include <resolv.h>
159a7e231eSAxel Dörfler #include <stdio.h>
169a7e231eSAxel Dörfler #include <string.h>
179a7e231eSAxel Dörfler #include <sys/socket.h>
189a7e231eSAxel Dörfler
19b4ec589bSAxel Dörfler #include <Box.h>
20a4a34e42SAxel Dörfler #include <Button.h>
21b4ec589bSAxel Dörfler #include <Catalog.h>
220ecdbff3SHumdinger #include <ControlLook.h>
23a4a34e42SAxel Dörfler #include <File.h>
24a4a34e42SAxel Dörfler #include <FindDirectory.h>
25a4a34e42SAxel Dörfler #include <LayoutBuilder.h>
26a4a34e42SAxel Dörfler #include <ListView.h>
27a4a34e42SAxel Dörfler #include <Path.h>
280ecdbff3SHumdinger #include <SeparatorView.h>
29a4a34e42SAxel Dörfler #include <ScrollView.h>
30b4ec589bSAxel Dörfler #include <StringView.h>
31d0b107f3SAxel Dörfler
32d0b107f3SAxel Dörfler #include "IPAddressControl.h"
33a4a34e42SAxel Dörfler
34a4a34e42SAxel Dörfler
35b4ec589bSAxel Dörfler static const int32 kMsgAddServer = 'adds';
36b4ec589bSAxel Dörfler static const int32 kMsgDeleteServer = 'dels';
37*e248c98eSJaidyn Ann static const int32 kMsgSelectServer = 'sels';
38b4ec589bSAxel Dörfler static const int32 kMsgMoveUp = 'mvup';
39b4ec589bSAxel Dörfler static const int32 kMsgMoveDown = 'mvdn';
40b4ec589bSAxel Dörfler static const int32 kMsgApply = 'aply';
41b4ec589bSAxel Dörfler
42b4ec589bSAxel Dörfler
43b4ec589bSAxel Dörfler #undef B_TRANSLATION_CONTEXT
44b4ec589bSAxel Dörfler #define B_TRANSLATION_CONTEXT "DNSSettingsView"
45a4a34e42SAxel Dörfler
46a4a34e42SAxel Dörfler
DNSSettingsView(BNetworkSettingsItem * item)473d7aaa30SAxel Dörfler DNSSettingsView::DNSSettingsView(BNetworkSettingsItem* item)
489a7e231eSAxel Dörfler :
493d7aaa30SAxel Dörfler BView("dns", 0),
503d7aaa30SAxel Dörfler fItem(item)
51a4a34e42SAxel Dörfler {
520ecdbff3SHumdinger BStringView* titleView = new BStringView("title",
530ecdbff3SHumdinger B_TRANSLATE("DNS settings"));
540ecdbff3SHumdinger titleView->SetFont(be_bold_font);
550ecdbff3SHumdinger titleView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
560ecdbff3SHumdinger
57a4a34e42SAxel Dörfler fServerListView = new BListView("nameservers");
58*e248c98eSJaidyn Ann fServerListView->SetSelectionMessage(new BMessage(kMsgSelectServer));
5938aa1d3bSHumdinger const char* serverLabel = B_TRANSLATE("Server:");
6038aa1d3bSHumdinger fTextControl = new IPAddressControl(AF_UNSPEC, serverLabel, "server");
610ecdbff3SHumdinger fTextControl->SetExplicitMinSize(BSize(fTextControl->StringWidth("5") * 16
6238aa1d3bSHumdinger + fTextControl->StringWidth(serverLabel), B_SIZE_UNSET));
63a4a34e42SAxel Dörfler
64b4ec589bSAxel Dörfler fAddButton = new BButton(B_TRANSLATE("Add"), new BMessage(kMsgAddServer));
65b4ec589bSAxel Dörfler fAddButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
66b4ec589bSAxel Dörfler fUpButton = new BButton(B_TRANSLATE("Move up"), new BMessage(kMsgMoveUp));
67b4ec589bSAxel Dörfler fUpButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
68*e248c98eSJaidyn Ann fUpButton->SetEnabled(false);
69b4ec589bSAxel Dörfler fDownButton = new BButton(B_TRANSLATE("Move down"),
70b4ec589bSAxel Dörfler new BMessage(kMsgMoveDown));
71b4ec589bSAxel Dörfler fDownButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
72*e248c98eSJaidyn Ann fDownButton->SetEnabled(false);
730ecdbff3SHumdinger fRemoveButton = new BButton(B_TRANSLATE("Remove"),
740ecdbff3SHumdinger new BMessage(kMsgDeleteServer));
75b4ec589bSAxel Dörfler fRemoveButton->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
76*e248c98eSJaidyn Ann fRemoveButton->SetEnabled(false);
770ecdbff3SHumdinger fDomain = new BTextControl(B_TRANSLATE("Domain:"), "", NULL);
78b4ec589bSAxel Dörfler fApplyButton = new BButton(B_TRANSLATE("Apply"), new BMessage(kMsgApply));
79b4ec589bSAxel Dörfler
800ecdbff3SHumdinger float spacing = be_control_look->DefaultItemSpacing();
810ecdbff3SHumdinger
820ecdbff3SHumdinger BGridView* serviceGridView = new BGridView();
830ecdbff3SHumdinger BLayoutBuilder::Grid<>(serviceGridView)
84a4a34e42SAxel Dörfler .Add(fTextControl, 0, 0)
85a4a34e42SAxel Dörfler .Add(fAddButton, 1, 0)
86a4a34e42SAxel Dörfler .Add(new BScrollView("scroll", fServerListView, 0, false, true),
87b4ec589bSAxel Dörfler 0, 1, 1, 3)
88a4a34e42SAxel Dörfler .Add(fUpButton, 1, 1)
89a4a34e42SAxel Dörfler .Add(fDownButton, 1, 2)
90a4a34e42SAxel Dörfler .Add(fRemoveButton, 1, 3)
910ecdbff3SHumdinger .SetColumnWeight(0, 10.f);
92b4ec589bSAxel Dörfler
93b4ec589bSAxel Dörfler BLayoutBuilder::Group<>(this, B_VERTICAL)
940ecdbff3SHumdinger .Add(titleView)
950ecdbff3SHumdinger .Add(serviceGridView)
960ecdbff3SHumdinger .Add(new BSeparatorView(B_HORIZONTAL))
970ecdbff3SHumdinger .Add(fDomain)
980ecdbff3SHumdinger .AddStrut(spacing)
99b4ec589bSAxel Dörfler .AddGroup(B_HORIZONTAL)
100b4ec589bSAxel Dörfler .AddGlue()
101b4ec589bSAxel Dörfler .Add(fApplyButton);
102a4a34e42SAxel Dörfler
103a4a34e42SAxel Dörfler _LoadDNSConfiguration();
104a4a34e42SAxel Dörfler }
105a4a34e42SAxel Dörfler
106a4a34e42SAxel Dörfler
~DNSSettingsView()1079a7e231eSAxel Dörfler DNSSettingsView::~DNSSettingsView()
1089a7e231eSAxel Dörfler {
1099a7e231eSAxel Dörfler }
1109a7e231eSAxel Dörfler
1119a7e231eSAxel Dörfler
112a4a34e42SAxel Dörfler status_t
Revert()113a4a34e42SAxel Dörfler DNSSettingsView::Revert()
114a4a34e42SAxel Dörfler {
115a4a34e42SAxel Dörfler int i;
116a4a34e42SAxel Dörfler for (i = 0; i < fRevertList.CountStrings(); i++) {
1179a7e231eSAxel Dörfler BStringItem* item = static_cast<BStringItem*>(
1189a7e231eSAxel Dörfler fServerListView->ItemAt(i));
119a4a34e42SAxel Dörfler if (item == NULL) {
120a4a34e42SAxel Dörfler item = new BStringItem("");
121a4a34e42SAxel Dörfler fServerListView->AddItem(item);
122a4a34e42SAxel Dörfler }
123a4a34e42SAxel Dörfler
124a4a34e42SAxel Dörfler item->SetText(fRevertList.StringAt(i));
125a4a34e42SAxel Dörfler }
126a4a34e42SAxel Dörfler
127a4a34e42SAxel Dörfler // Now remove any extra item
128a4a34e42SAxel Dörfler for (; i < fServerListView->CountItems(); i++)
129a4a34e42SAxel Dörfler delete fServerListView->RemoveItem(i);
130a4a34e42SAxel Dörfler
131a4a34e42SAxel Dörfler return B_OK;
132a4a34e42SAxel Dörfler }
133a4a34e42SAxel Dörfler
134a4a34e42SAxel Dörfler
1356a290205SAxel Dörfler bool
IsRevertable() const1366a290205SAxel Dörfler DNSSettingsView::IsRevertable() const
1376a290205SAxel Dörfler {
1386a290205SAxel Dörfler // TODO
1396a290205SAxel Dörfler return false;
1406a290205SAxel Dörfler }
1416a290205SAxel Dörfler
1426a290205SAxel Dörfler
143b4ec589bSAxel Dörfler void
AttachedToWindow()144b4ec589bSAxel Dörfler DNSSettingsView::AttachedToWindow()
145b4ec589bSAxel Dörfler {
146b4ec589bSAxel Dörfler fAddButton->SetTarget(this);
147b4ec589bSAxel Dörfler fRemoveButton->SetTarget(this);
148b4ec589bSAxel Dörfler fUpButton->SetTarget(this);
149b4ec589bSAxel Dörfler fDownButton->SetTarget(this);
150b4ec589bSAxel Dörfler
151*e248c98eSJaidyn Ann fServerListView->SetTarget(this);
152*e248c98eSJaidyn Ann
153b4ec589bSAxel Dörfler fTextControl->SetTarget(this);
154b4ec589bSAxel Dörfler
155b4ec589bSAxel Dörfler fApplyButton->SetTarget(this);
156b4ec589bSAxel Dörfler }
157b4ec589bSAxel Dörfler
158b4ec589bSAxel Dörfler
159b4ec589bSAxel Dörfler void
MessageReceived(BMessage * message)160b4ec589bSAxel Dörfler DNSSettingsView::MessageReceived(BMessage* message)
161b4ec589bSAxel Dörfler {
162b4ec589bSAxel Dörfler switch (message->what) {
163b4ec589bSAxel Dörfler case kMsgAddServer:
164b4ec589bSAxel Dörfler {
165b4ec589bSAxel Dörfler const char* address = fTextControl->Text();
166b4ec589bSAxel Dörfler fServerListView->AddItem(new BStringItem(address));
167b4ec589bSAxel Dörfler break;
168b4ec589bSAxel Dörfler }
169b4ec589bSAxel Dörfler case kMsgDeleteServer:
170b4ec589bSAxel Dörfler delete fServerListView->RemoveItem(
171b4ec589bSAxel Dörfler fServerListView->CurrentSelection());
172b4ec589bSAxel Dörfler break;
173b4ec589bSAxel Dörfler
174b4ec589bSAxel Dörfler case kMsgMoveUp:
175b4ec589bSAxel Dörfler {
176b4ec589bSAxel Dörfler int index = fServerListView->CurrentSelection();
177b4ec589bSAxel Dörfler if (index > 0)
178b4ec589bSAxel Dörfler fServerListView->SwapItems(index, index - 1);
179b4ec589bSAxel Dörfler break;
180b4ec589bSAxel Dörfler }
181b4ec589bSAxel Dörfler case kMsgMoveDown:
182b4ec589bSAxel Dörfler {
183b4ec589bSAxel Dörfler int index = fServerListView->CurrentSelection();
184b4ec589bSAxel Dörfler if (index < fServerListView->CountItems() - 1)
185b4ec589bSAxel Dörfler fServerListView->SwapItems(index, index + 1);
186b4ec589bSAxel Dörfler break;
187b4ec589bSAxel Dörfler }
188*e248c98eSJaidyn Ann case kMsgSelectServer:
189*e248c98eSJaidyn Ann {
190*e248c98eSJaidyn Ann bool enabled = false;
191*e248c98eSJaidyn Ann if (fServerListView->CurrentSelection() > -1)
192*e248c98eSJaidyn Ann enabled = true;
193*e248c98eSJaidyn Ann
194*e248c98eSJaidyn Ann fUpButton->SetEnabled(enabled);
195*e248c98eSJaidyn Ann fDownButton->SetEnabled(enabled);
196*e248c98eSJaidyn Ann fRemoveButton->SetEnabled(enabled);
197*e248c98eSJaidyn Ann break;
198*e248c98eSJaidyn Ann }
199b4ec589bSAxel Dörfler case kMsgApply:
2003d7aaa30SAxel Dörfler if (_SaveDNSConfiguration() == B_OK)
2013d7aaa30SAxel Dörfler fItem->NotifySettingsUpdated();
202b4ec589bSAxel Dörfler break;
203b4ec589bSAxel Dörfler
204b4ec589bSAxel Dörfler default:
205b4ec589bSAxel Dörfler BView::MessageReceived(message);
206b4ec589bSAxel Dörfler break;
207b4ec589bSAxel Dörfler }
208b4ec589bSAxel Dörfler }
209b4ec589bSAxel Dörfler
210b4ec589bSAxel Dörfler
211a4a34e42SAxel Dörfler status_t
_LoadDNSConfiguration()212a4a34e42SAxel Dörfler DNSSettingsView::_LoadDNSConfiguration()
213a4a34e42SAxel Dörfler {
214e587c279SAxel Dörfler if (res_init() != 0)
215e587c279SAxel Dörfler return B_ERROR;
216e587c279SAxel Dörfler
2171eabd148SAugustin Cavalier struct __res_state state;
2181eabd148SAugustin Cavalier memset(&state, 0, sizeof(struct __res_state));
219a4a34e42SAxel Dörfler
2201eabd148SAugustin Cavalier if (res_ninit(&state) != 0)
2211eabd148SAugustin Cavalier return B_ERROR;
2221eabd148SAugustin Cavalier
2231eabd148SAugustin Cavalier for (int i = 0; i < state.nscount; i++) {
2241eabd148SAugustin Cavalier char* address = inet_ntoa(state.nsaddr_list[i].sin_addr);
225a4a34e42SAxel Dörfler fServerListView->AddItem(new BStringItem(address));
226a4a34e42SAxel Dörfler fRevertList.Add(address);
227a4a34e42SAxel Dörfler }
228a4a34e42SAxel Dörfler
2291eabd148SAugustin Cavalier fDomain->SetText(state.dnsrch[0]);
230d585e4c3SAdrien Destugues
2311eabd148SAugustin Cavalier res_nclose(&state);
232a4a34e42SAxel Dörfler return B_OK;
233a4a34e42SAxel Dörfler }
234a4a34e42SAxel Dörfler
235a4a34e42SAxel Dörfler
236a4a34e42SAxel Dörfler status_t
_SaveDNSConfiguration()237a4a34e42SAxel Dörfler DNSSettingsView::_SaveDNSConfiguration()
238a4a34e42SAxel Dörfler {
239a4a34e42SAxel Dörfler BPath path;
240a4a34e42SAxel Dörfler status_t status;
241a4a34e42SAxel Dörfler status = find_directory(B_SYSTEM_SETTINGS_DIRECTORY, &path);
242a4a34e42SAxel Dörfler if (status != B_OK)
243a4a34e42SAxel Dörfler return status;
244a4a34e42SAxel Dörfler
245a4a34e42SAxel Dörfler path.Append("network/resolv.conf");
246a4a34e42SAxel Dörfler
247a4a34e42SAxel Dörfler BFile file(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
248a4a34e42SAxel Dörfler if (file.InitCheck() != B_OK) {
249a4a34e42SAxel Dörfler fprintf(stderr, "failed to open %s for writing: %s\n", path.Path(),
250a4a34e42SAxel Dörfler strerror(file.InitCheck()));
251a4a34e42SAxel Dörfler return file.InitCheck();
252a4a34e42SAxel Dörfler }
253a4a34e42SAxel Dörfler
2545186fb7eSRob Gill BString content("# Static DNS entries\n# Generated by Network preferences\n");
255a4a34e42SAxel Dörfler
2569a7e231eSAxel Dörfler for (int i = 0; i < fServerListView->CountItems(); i++) {
2579a7e231eSAxel Dörfler BString item = ((BStringItem*)fServerListView->ItemAt(i))->Text();
2589a7e231eSAxel Dörfler if (item.Length() > 0)
259a4a34e42SAxel Dörfler content << "nameserver\t" << item.String() << "\n";
260a4a34e42SAxel Dörfler }
261a4a34e42SAxel Dörfler
262a4a34e42SAxel Dörfler if (strlen(fDomain->Text()) > 0)
263a4a34e42SAxel Dörfler content << "domain\t" << fDomain->Text() << "\n";
264a4a34e42SAxel Dörfler
2655186fb7eSRob Gill content << "# Dynamic DNS entries\n# may be altered by DHCP\n";
2665186fb7eSRob Gill
267a4a34e42SAxel Dörfler return file.Write(content.String(), content.Length());
268a4a34e42SAxel Dörfler }
269