-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipresolver.cpp
187 lines (177 loc) · 5.37 KB
/
ipresolver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include "ipresolver.h"
#include "unixsignalhandler.h"
#include <QProcess>
#include <QDebug>
#include <QStack>
#include <QThread>
#include <QHostAddress>
IpResolver* IpResolver::instance = NULL;
IpResolver::IpResolver() :
QObject()
{
#ifdef __APPLE__
addMapping("::1", "", "lo0");
#elif __GNUC__
addMapping("::1", "", "lo");
#endif
}
IpResolver* IpResolver::getInstance() {
static QMutex mutex;
mutex.lock();
if (instance == NULL) {
instance = new IpResolver();
}
mutex.unlock();
return instance;
}
void IpResolver::addMapping(QString ip, QString mac, QString interface) {
struct ip_mac_mapping newmap;
newmap.interface = interface;
newmap.mac = mac;
newmap.ip = QHostAddress(ip);
if (mappings.contains(ip)) {
return;
}
mutex.lock();
mappings.insert(ip, newmap);
mutex.unlock();
}
struct ip_mac_mapping IpResolver::getMapping(QString ip) {
QHostAddress localIp(ip);
mutex.lock();
if (mappings.contains(ip)) {
mutex.unlock();
return mappings.value(ip);
} else {
mutex.unlock();
char buf[3000];
int length;
// is it a local address ?
QProcess testIfconfig;
testIfconfig.start("/sbin/ifconfig");
testIfconfig.waitForReadyRead();
while ((length = testIfconfig.readLine(buf, 3000))) {
QString curLine(buf);
QStringList list = curLine.split(" ", QString::SkipEmptyParts);
foreach (QString value, list) {
#ifndef __APPLE__
value.chop(3);
#endif
QHostAddress cmp(value);
if (cmp == localIp) {
qDebug() << "Found local IP" << value;
#ifdef __APPLE__
this->addMapping(ip, "", "lo0");
#elif __GNUC__
this->addMapping(ip, "", "lo");
#endif
testIfconfig.close();
return getMapping(ip);
}
}
}
testIfconfig.close();
// check kernel neighbor cache
QProcess ndp;
#ifdef __APPLE__
ndp.start("ndp -an");
while (ndp.waitForReadyRead(500)) {
while ((length = ndp.readLine(buf, 3000))) {
QString curLine(buf);
QStringList list = curLine.split(" ", QString::SkipEmptyParts);
QHostAddress cmp(list.at(0));
if (localIp == cmp) {
qDebug() << "Found IP in neighbor cache";
if (list.at(1) != "(incomplete)") {
qDebug() << "Mapping is" << list.at(1) << list.at(2);
this->addMapping(ip, list.at(1), list.at(2));
ndp.close();
return getMapping(ip);
}
}
}
}
ndp.close();
#elif __GNUC__
ndp.start("ip -6 neigh");
ndp.waitForReadyRead();
while (ndp.waitForReadyRead(500)) {
while ((length = ndp.readLine(buf, 3000))) {
QString curLine(buf);
QStringList list = curLine.split(" ", QString::SkipEmptyParts);
QHostAddress cmp(list.at(0));
if (cmp == localIp) {
this->addMapping(ip, list.at(4), list.at(2));
ndp.close();
return getMapping(ip);
}
}
}
ndp.close();
#endif
qDebug() << "Returning nullMapping";
struct ip_mac_mapping nullMapping;
// fail
return nullMapping;
}
}
QStack<QString> IpResolver::getActiveInterfaces() {
// we should list all interfaces but for now we just go with the default interface and
// the loopback default
QStack<QString> activeIfaces;
#ifdef __APPLE__
activeIfaces.push("lo0");
#elif __GNUC__
activeIfaces.push("lo");
#endif
activeIfaces.push(getDefaultInterface());
return activeIfaces;
}
QString IpResolver::getDefaultInterface() {
IpResolver* r = IpResolver::getInstance();
if (!(r->defaultInterface.isEmpty())) {
return r->defaultInterface;
}
#ifdef __APPLE__
QProcess netstat;
netstat.start("netstat -nr");
netstat.waitForReadyRead();
char buf[3000];
int length;
while ((length = netstat.readLine(buf, 3000))) {
buf[length - 1] = '\0'; // remove "\n"
QString curLine(buf);
if (curLine.startsWith("default")) {
QStringList list = curLine.split(" ", QString::SkipEmptyParts);
if (list.at(1).contains(":")) {
netstat.close();
r->defaultInterface = list.at(3);
return r->defaultInterface;
}
}
}
netstat.close();
#elif __GNUC__
QProcess route;
route.start("route -n6");
route.waitForReadyRead();
char buf[3000];
int length;
while ((length = route.readLine(buf, 3000))) {
buf[length - 1] = '\0'; // remove "\n"
QString curLine(buf);
if (curLine.startsWith("::/0")) {
QStringList list = curLine.split(" ", QString::SkipEmptyParts);
if (list.at(2) != "::") {
route.close();
r->defaultInterface = list.at(6);
return r->defaultInterface;
}
}
}
route.close();
#endif
qWarning() << "The host has no IPv6 default route!";
UnixSignalHandler::termSignalHandler(0);
return QString();
}