VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp@ 49201

Last change on this file since 49201 was 49201, checked in by vboxsync, 12 years ago

HostDnsServiceLinux.cpp: inotify based watcher for /etc/resolv.conf.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.5 KB
Line 
1/* $Id: HostDnsServiceLinux.cpp 49201 2013-10-21 02:49:37Z vboxsync $ */
2/** @file
3 * Linux specific DNS information fetching.
4 */
5
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/assert.h>
19#include <iprt/err.h>
20#include <iprt/initterm.h>
21#include <iprt/file.h>
22#include <iprt/log.h>
23#include <iprt/stream.h>
24#include <iprt/string.h>
25#include <iprt/semaphore.h>
26#include <iprt/thread.h>
27
28#include "../HostDnsService.h"
29
30#include <errno.h>
31#include <poll.h>
32#include <string.h>
33#include <unistd.h>
34
35#include <fcntl.h>
36
37#include <sys/inotify.h>
38#include <sys/types.h>
39#include <sys/socket.h>
40
41#include <string>
42
43static RTTHREAD g_DnsMonitoringThread;
44static RTSEMEVENT g_DnsInitEvent;
45static int g_DnsMonitorStop[2];
46
47class FileDescriptor
48{
49 public:
50 FileDescriptor(int d = -1):fd(d){}
51
52 virtual ~FileDescriptor() {
53 if (fd != -1)
54 close(fd);
55 }
56
57 int fileDescriptor() const {return fd;}
58
59 protected:
60 int fd;
61};
62
63
64class AutoNotify:public FileDescriptor
65{
66 public:
67 AutoNotify()
68 {
69 FileDescriptor::fd = inotify_init();
70 AssertReturnVoid(FileDescriptor::fd != -1);
71 }
72
73};
74
75
76class AutoWatcher:public FileDescriptor
77{
78 public:
79 AutoWatcher(const AutoNotify& notifier, const std::string& filename, uint32_t mask = IN_CLOSE_WRITE)
80 :name(filename)
81 {
82 nfd = notifier.fileDescriptor();
83 fd = inotify_add_watch(nfd, name.c_str(), mask);
84 AssertMsgReturnVoid(fd != -1, ("failed to add watcher %s\n", name.c_str()));
85
86 int opt = fcntl(fd, F_GETFL);
87 opt |= O_NONBLOCK;
88 fcntl(fd, F_SETFL, opt);
89 }
90
91 ~AutoWatcher()
92 {
93 int rc = inotify_rm_watch(nfd, fd);
94 AssertMsgReturnVoid(rc != -1, ("Can't detach watcher %d from %d (%d: %s)\n", nfd, fd,
95 errno, strerror(errno)));
96 }
97
98 private:
99 std::string name;
100 int nfd;
101};
102
103
104int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
105{
106 AutoNotify a;
107 HostDnsServiceLinux *dns = static_cast<HostDnsServiceLinux *>(pvUser);
108 AutoWatcher w(a, std::string(dns->resolvConf().c_str()));
109
110 int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop);
111 AssertMsgReturn(rc == 0, ("socketpair: failed (%d: %s)\n", errno, strerror(errno)), E_FAIL);
112
113 FileDescriptor stopper0(g_DnsMonitorStop[0]);
114 FileDescriptor stopper1(g_DnsMonitorStop[1]);
115
116 pollfd polls[2];
117 RT_ZERO(polls);
118
119 polls[0].fd = a.fileDescriptor();
120 polls[0].events = POLLIN;
121
122 polls[1].fd = g_DnsMonitorStop[1];
123 polls[1].events = POLLIN;
124
125 RTSemEventSignal(g_DnsInitEvent);
126
127 while(true)
128 {
129 rc = poll(polls, 2, -1);
130 if (rc == -1)
131 continue;
132
133 AssertMsgReturn( ((polls[0].revents & (POLLERR|POLLNVAL)) == 0)
134 && ((polls[1].revents & (POLLERR|POLLNVAL)) == 0),
135 ("Debug Me"), VERR_INTERNAL_ERROR);
136
137 if (polls[1].revents & POLLIN)
138 return VINF_SUCCESS; /* time to shutdown */
139
140 if (polls[0].revents & POLLIN)
141 {
142 RTCritSectEnter(&dns->::HostDnsService::m_hCritSect);
143 dns->update();
144 RTCritSectLeave(&dns->::HostDnsService::m_hCritSect);
145 polls[0].revents = 0;
146
147 inotify_event ev;
148 rc = read(a.fileDescriptor(), static_cast<void *>(&ev), sizeof(ev));
149 AssertMsg(rc == sizeof(ev) && ev.wd == w.fileDescriptor(), ("Hmm, debug me"));
150 }
151 }
152}
153
154
155HRESULT HostDnsServiceLinux::init(const VirtualBox *aParent)
156{
157 HRESULT hrc = HostDnsServiceResolvConf::init(aParent);
158 AssertComRCReturnRC(hrc);
159
160 int rc = RTThreadCreate(&g_DnsMonitoringThread, HostDnsServiceLinux::hostMonitoringRoutine,
161 this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
162 AssertRCReturn(rc, E_FAIL);
163
164 rc = RTSemEventCreate(&g_DnsInitEvent);
165 AssertRCReturn(rc, E_FAIL);
166
167 RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
168
169 return S_OK;
170}
171
172
173void HostDnsServiceLinux::stop()
174{
175 send(g_DnsMonitorStop[0], "", 1, 0);
176}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette