xref: /haiku/src/add-ons/network_settings/dnsclient/DNSSettingsView.cpp (revision e248c98eb8cb3b0521ed3316cb2e1c71a721b1f9)
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