Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dap-ui-sdk
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
7
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
dap
dap-ui-sdk
Commits
60919b48
Commit
60919b48
authored
2 months ago
by
Danil Martynenko
Committed by
Danil Martynenko
2 months ago
Browse files
Options
Downloads
Patches
Plain Diff
[*] DapUtun refactored, set dns, clear dns
parent
bde61a11
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
vpn/client/darwin/DapUtun.cpp
+285
-191
285 additions, 191 deletions
vpn/client/darwin/DapUtun.cpp
vpn/client/darwin/DapUtun.h
+33
-1
33 additions, 1 deletion
vpn/client/darwin/DapUtun.h
with
318 additions
and
192 deletions
vpn/client/darwin/DapUtun.cpp
+
285
−
191
View file @
60919b48
...
@@ -21,38 +21,11 @@ This file is part of DAP UI SDK the open source project
...
@@ -21,38 +21,11 @@ This file is part of DAP UI SDK the open source project
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include
<QtDebug>
#include
<QProcess>
#include
<QFile>
#include
<stdarg.h>
#include
<sys/types.h>
#include
<sys/ioctl.h>
#include
<sys/socket.h>
#include
<sys/sys_domain.h>
#include
<sys/kern_control.h>
#include
<net/if_utun.h>
#include
<errno.h>
#include
<string.h>
#include
<unistd.h>
#include
<fcntl.h>
#include
"DapUtils.h"
#include
"DapUtils.h"
#include
"DapTunUnixAbstract.h"
#include
"QtCore/qdebug.h"
#include
"darwin/DapUtun.h"
#include
"darwin/DapUtun.h"
#include
"DapTunWorkerUnix.h"
#include
"DapNetworkMonitor.h"
#include
"SigUnixHandler.h"
/**
* @brief DapUtun::DapUtun
*/
DapUtun
::
DapUtun
()
DapUtun
::
DapUtun
()
:
DapTunUnixAbstract
()
:
DapTunUnixAbstract
()
{
{
// List of Apple addresses needed to be routed directly through the tunnel
// List of Apple addresses needed to be routed directly through the tunnel
appleAdditionalRoutes
=
QStringList
({
appleAdditionalRoutes
=
QStringList
({
...
@@ -71,50 +44,81 @@ DapUtun::DapUtun()
...
@@ -71,50 +44,81 @@ DapUtun::DapUtun()
this
,
&
DapUtun
::
tunDeviceDestroy
,
Qt
::
DirectConnection
);
this
,
&
DapUtun
::
tunDeviceDestroy
,
Qt
::
DirectConnection
);
}
}
/**
* @brief DapUtun::requestTunDeviceCreate
void
DapUtun
::
executeCommand
(
const
QString
&
cmd
)
*/
{
qDebug
()
<<
"Executing command:"
<<
cmd
;
QProcess
process
;
process
.
start
(
cmd
);
if
(
!
process
.
waitForFinished
(
2000
))
{
qWarning
()
<<
"Command failed to execute:"
<<
process
.
errorString
();
return
;
}
int
ret
=
process
.
exitCode
();
QString
output
=
process
.
readAllStandardOutput
();
QString
errorOutput
=
process
.
readAllStandardError
();
qDebug
()
<<
"Command output:"
<<
output
.
trimmed
();
if
(
!
errorOutput
.
isEmpty
())
{
qWarning
()
<<
"Command error output:"
<<
errorOutput
.
trimmed
();
}
qDebug
()
<<
"Command returned exit code:"
<<
ret
;
if
(
ret
!=
0
)
{
qWarning
()
<<
"Command failed with exit code:"
<<
ret
;
}
}
void
DapUtun
::
tunDeviceCreate
()
void
DapUtun
::
tunDeviceCreate
()
{
{
qDebug
()
<<
"[DapUtun::tunDeviceCreate]"
;
qDebug
()
<<
"[DapUtun::tunDeviceCreate]"
;
if
(
m_tunSocket
>
0
)
{
if
(
m_tunSocket
>
0
)
{
qInfo
()
<<
"Socket already open"
;
qInfo
()
<<
"Socket already open"
;
return
;
return
;
}
}
// Prepare structs
// Lambda function to retrieve error messages
auto
getErrorString
=
[]()
->
QString
{
int
err
=
errno
;
char
errbuf
[
256
];
::
strerror_r
(
err
,
errbuf
,
sizeof
(
errbuf
));
return
QString
(
"%1 (code %2)"
).
arg
(
errbuf
).
arg
(
err
);
};
// Initialize the control structure
struct
ctl_info
l_ctl_info
=
{
0
};
struct
ctl_info
l_ctl_info
=
{
0
};
// Copy utun control name
// Copy utun control name
if
(
::
strlcpy
(
l_ctl_info
.
ctl_name
,
UTUN_CONTROL_NAME
,
sizeof
(
l_ctl_info
.
ctl_name
))
if
(
::
strlcpy
(
l_ctl_info
.
ctl_name
,
UTUN_CONTROL_NAME
,
sizeof
(
l_ctl_info
.
ctl_name
))
>=
sizeof
(
l_ctl_info
.
ctl_name
)){
>=
sizeof
(
l_ctl_info
.
ctl_name
))
{
emit
error
(
QString
(
"UTUN_CONTROL_NAME % is too long"
).
arg
(
UTUN_CONTROL_NAME
));
emit
error
(
QString
(
"UTUN_CONTROL_NAME %
1
is too long"
).
arg
(
UTUN_CONTROL_NAME
));
return
;
return
;
}
}
// Create utun socket
// Create utun socket
int
l_tun_fd
=
::
socket
(
PF_SYSTEM
,
SOCK_DGRAM
,
SYSPROTO_CONTROL
);
int
l_tun_fd
=
::
socket
(
PF_SYSTEM
,
SOCK_DGRAM
,
SYSPROTO_CONTROL
);
if
(
l_tun_fd
<
0
){
if
(
l_tun_fd
<
0
)
{
int
l_errno
=
errno
;
emit
error
(
QString
(
"Opening utun device control (SYSPROTO_CONTROL) error: %1"
)
char
l_errbuf
[
256
];
.
arg
(
getErrorString
()));
::
strerror_r
(
l_errno
,
l_errbuf
,
sizeof
(
l_errbuf
));
emit
error
(
QString
(
"Opening utun device control (SYSPROTO_CONTROL) error: '%1' (code %2)"
).
arg
(
l_errbuf
).
arg
(
l_errno
));
return
;
return
;
}
}
qInfo
()
<<
"Utun SYSPROTO_CONTROL descriptor obtained"
;
qInfo
()
<<
"Utun SYSPROTO_CONTROL descriptor obtained"
;
// Pass control structure to the utun socket
// Retrieve control ID via ioctl
if
(
::
ioctl
(
l_tun_fd
,
CTLIOCGINFO
,
&
l_ctl_info
)
<
0
){
if
(
::
ioctl
(
l_tun_fd
,
CTLIOCGINFO
,
&
l_ctl_info
)
<
0
)
{
int
l_errno
=
errno
;
::
close
(
l_tun_fd
);
char
l_errbuf
[
256
];
emit
error
(
QString
(
"Can't execute ioctl(CTLIOCGINFO): %1"
).
arg
(
getErrorString
()));
::
strerror_r
(
l_errno
,
l_errbuf
,
sizeof
(
l_errbuf
));
emit
error
(
QString
(
"Can't execute ioctl(CTLIOCGINFO): '%1' (code %1)"
).
arg
(
l_errbuf
).
arg
(
l_errno
));
return
;
return
;
}
}
qInfo
()
<<
"Utun CTLIOCGINFO structure passed through ioctl"
;
qInfo
()
<<
"Utun CTLIOCGINFO structure passed through ioctl"
;
// Trying to connect with one of utunX devices
// Trying to connect with one of utunX devices
int
l_ret
=
-
1
;
int
l_ret
=
-
1
;
for
(
int
l_unit
=
0
;
l_unit
<
256
;
l_unit
++
){
for
(
int
l_unit
=
0
;
l_unit
<
256
;
l_unit
++
)
{
struct
sockaddr_ctl
l_sa_ctl
=
{
0
};
struct
sockaddr_ctl
l_sa_ctl
=
{
0
};
l_sa_ctl
.
sc_id
=
l_ctl_info
.
ctl_id
;
l_sa_ctl
.
sc_id
=
l_ctl_info
.
ctl_id
;
l_sa_ctl
.
sc_len
=
sizeof
(
l_sa_ctl
);
l_sa_ctl
.
sc_len
=
sizeof
(
l_sa_ctl
);
...
@@ -122,234 +126,324 @@ void DapUtun::tunDeviceCreate()
...
@@ -122,234 +126,324 @@ void DapUtun::tunDeviceCreate()
l_sa_ctl
.
ss_sysaddr
=
AF_SYS_CONTROL
;
l_sa_ctl
.
ss_sysaddr
=
AF_SYS_CONTROL
;
l_sa_ctl
.
sc_unit
=
l_unit
+
1
;
l_sa_ctl
.
sc_unit
=
l_unit
+
1
;
// If connect successful, new utunX device should be created
l_ret
=
::
connect
(
l_tun_fd
,
reinterpret_cast
<
struct
sockaddr
*>
(
&
l_sa_ctl
),
sizeof
(
l_sa_ctl
));
l_ret
=
::
connect
(
l_tun_fd
,
(
struct
sockaddr
*
)
&
l_sa_ctl
,
sizeof
(
l_sa_ctl
));
if
(
l_ret
==
0
)
if
(
l_ret
==
0
)
break
;
break
;
}
}
// Check if the previous step was successful
if
(
l_ret
<
0
){
if
(
l_ret
<
0
)
{
int
l_errno
=
errno
;
::
close
(
l_tun_fd
);
char
l_errbuf
[
256
];
emit
error
(
QString
(
"Can't create utun device: %1"
).
arg
(
getErrorString
()));
::
strerror_r
(
l_errno
,
l_errbuf
,
sizeof
(
l_errbuf
));
emit
error
(
QString
(
"Can't create utun device: '%1' (code %2)"
).
arg
(
l_errbuf
).
arg
(
l_errno
));
return
;
return
;
}
}
// Get iface name of newly created utun dev.
// Get iface name of newly created utun dev.
qInfo
()
<<
"Utun device created"
;
qInfo
()
<<
"Utun device created"
;
char
l_utunname
[
20
];
l_utunname
[
0
]
=
'\0'
;
// Retrieve the name of the utun network interface
char
l_utunname
[
20
]
=
{
0
};
socklen_t
l_utunname_len
=
sizeof
(
l_utunname
);
socklen_t
l_utunname_len
=
sizeof
(
l_utunname
);
if
(
::
getsockopt
(
l_tun_fd
,
SYSPROTO_CONTROL
,
UTUN_OPT_IFNAME
,
l_utunname
,
&
l_utunname_len
)
){
if
(
::
getsockopt
(
l_tun_fd
,
SYSPROTO_CONTROL
,
UTUN_OPT_IFNAME
,
l_utunname
,
&
l_utunname_len
))
{
int
l_errno
=
errno
;
::
close
(
l_tun_fd
);
char
l_errbuf
[
256
];
emit
error
(
QString
(
"Can't get utun device name: %1"
).
arg
(
getErrorString
()));
::
strerror_r
(
l_errno
,
l_errbuf
,
sizeof
(
l_errbuf
));
emit
error
(
QString
(
"Can't get utun device name: '%s' (code %d)"
).
arg
(
l_errbuf
).
arg
(
l_errno
));
return
;
return
;
}
}
m_tunDeviceName
=
QString
::
fromLatin1
(
l_utunname
,
l_utunname_len
-
1
);
qInfo
()
<<
"Created utun "
<<
m_tunDeviceName
<<
" network interface"
;
/* this is the special file descriptor that the caller will use to talk
/* this is the special file descriptor that the caller will use to talk
* with the virtual interface */
* with the virtual interface */
m_tunDeviceName
=
QString
::
fromLatin1
(
l_utunname
,
l_utunname_len
-
1
);
qInfo
()
<<
"Created utun"
<<
m_tunDeviceName
<<
"network interface"
;
m_tunSocket
=
l_tun_fd
;
m_tunSocket
=
l_tun_fd
;
}
}
/**
* @brief Detects active interface by default routing to 8.8.8.8
* @return Returns current active internet interface
*/
QString
DapUtun
::
getInternetInterface
()
QString
DapUtun
::
getInternetInterface
()
{
{
return
DapUtils
::
shellCmd
(
"route get 8.8.8.8 | grep interface | awk '{print $2;}'"
);
return
DapUtils
::
shellCmd
(
"route get 8.8.8.8 | grep interface | awk '{print $2;}'"
);
}
}
/**
* @brief DapUtun::saveCurrentConnectionInterfaceData
*/
void
DapUtun
::
saveCurrentConnectionInterfaceData
()
void
DapUtun
::
saveCurrentConnectionInterfaceData
()
{
{
m_lastUsedConnectionDevice
=
getInternetInterface
();
qDebug
()
<<
"Current internet interface:"
<<
m_lastUsedConnectionDevice
;
m_lastUsedConnectionDevice
=
this
->
getInternetInterface
();
QString
cmdList
=
QString
(
"networksetup -listnetworkserviceorder | grep 'Hardware Port' | grep %1"
)
qDebug
()
<<
"Current internet interface "
<<
m_lastUsedConnectionDevice
;
.
arg
(
m_lastUsedConnectionDevice
)
;
QString
result
=
DapUtils
::
shellCmd
(
QString
(
"networksetup -listnetworkserviceorder | grep 'Hardware Port' | grep %1"
).
arg
(
m_lastUsedConnectionDevice
)
);
QString
result
=
DapUtils
::
shellCmd
(
cmdList
);
QStringList
res1
=
result
.
split
(
":"
);
// Break down answer by Hardware port: and Device
QStringList
parts
=
result
.
split
(
":"
);
if
(
parts
.
length
()
<
3
)
{
if
(
res1
.
length
()
<
3
)
{
qWarning
()
<<
"Unable to retrieve connection interface name! Command output:"
<<
result
;
qWarning
()
<<
"Can't get current connection interface name! Command returns "
<<
result
;
return
;
return
;
}
}
QStringList
res2
=
res1
[
1
].
split
(
","
);
// Split from ,Device
QStringList
interfaceParts
=
parts
[
1
].
split
(
","
);
if
(
interfaceParts
.
length
()
<
2
)
{
if
(
res2
.
length
()
<
2
)
{
qWarning
()
<<
"Unexpected format from networksetup command! Command output:"
<<
result
;
qWarning
()
<<
" Wrong networksetup answer! Command returns "
<<
result
;
return
;
return
;
}
}
m_lastUsedConnectionName
=
res2
[
0
].
trimmed
();
m_lastUsedConnectionName
=
interfaceParts
[
0
].
trimmed
();
qDebug
()
<<
"Current internet connection name"
<<
m_lastUsedConnectionName
;
qDebug
()
<<
"Current internet connection name:"
<<
m_lastUsedConnectionName
;
result
=
DapUtils
::
shellCmd
(
QString
(
"networksetup -getinfo
\"
%1
\"
| grep Router"
).
arg
(
m_lastUsedConnectionName
));
QString
cmdGetInfo
=
QString
(
"networksetup -getinfo
\"
%1
\"
| grep Router"
)
QStringList
res3
=
result
.
split
(
"
\n
"
,
Qt
::
SkipEmptyParts
);
.
arg
(
m_lastUsedConnectionName
);
if
(
res3
.
length
()
<
1
)
{
result
=
DapUtils
::
shellCmd
(
cmdGetInfo
);
qWarning
()
<<
"No default router at all"
;
}
else
{
QStringList
infoLines
=
result
.
split
(
"
\n
"
,
Qt
::
SkipEmptyParts
);
QStringList
res4
=
res3
[
0
].
split
(
":"
);
if
(
infoLines
.
isEmpty
())
{
if
(
res3
.
length
()
!=
2
)
{
qWarning
()
<<
"No default router found."
;
qWarning
()
<<
"No default route address in line"
;
}
else
{
}
else
{
QStringList
routerParts
=
infoLines
.
first
().
split
(
":"
);
m_defaultGwOld
=
res4
[
1
]
==
"none"
?
QString
()
:
res4
[
1
];
if
(
routerParts
.
length
()
!=
2
)
{
qWarning
()
<<
"Unexpected default router line format:"
<<
infoLines
.
first
();
}
else
{
QString
routerValue
=
routerParts
[
1
].
trimmed
();
m_defaultGwOld
=
(
routerValue
==
"none"
)
?
QString
()
:
routerValue
;
}
}
}
}
qInfo
()
<<
"DeviceName name:"
<<
m_lastUsedConnectionDevice
qInfo
()
<<
"Device Name:"
<<
m_lastUsedConnectionDevice
<<
"Interface Name:"
<<
m_lastUsedConnectionName
<<
"Interface Name:"
<<
m_lastUsedConnectionName
<<
"Router"
<<
m_defaultGwOld
<<
"Router:"
<<
m_defaultGwOld
;
;
}
}
QStringList
DapUtun
::
getNetworkServices
()
{
QProcess
process
;
process
.
start
(
"networksetup"
,
QStringList
()
<<
"-listallnetworkservices"
);
/**
if
(
!
process
.
waitForFinished
(
5000
))
{
* @brief DapUtun::onWorkerStarted
qWarning
()
<<
"Failed to get list of network services:"
<<
process
.
errorString
();
*/
return
QStringList
();
void
DapUtun
::
onWorkerStarted
()
}
{
qDebug
()
<<
"tunnelCreate()"
;
QStringList
lines
=
QString
(
process
.
readAllStandardOutput
()).
split
(
"
\n
"
,
Qt
::
SkipEmptyParts
);
if
(
lines
.
size
()
<
2
)
{
qWarning
()
<<
"No valid network services found."
;
return
QStringList
();
}
return
lines
.
mid
(
1
);
}
QString
DapUtun
::
getDNSServers
(
const
QString
&
service
)
{
QProcess
process
;
QProcess
process
;
process
.
start
(
"networksetup"
,
QStringList
()
<<
"-getdnsservers"
<<
service
);
if
(
!
process
.
waitForFinished
(
5000
))
{
qWarning
()
<<
"Timeout while getting DNS for service"
<<
service
<<
":"
<<
process
.
errorString
();
return
QString
();
}
if
(
m_tunSocket
<=
0
)
{
return
process
.
readAllStandardOutput
().
trimmed
();
qCritical
()
<<
"Can't bring up network interface"
;
}
return
;
bool
DapUtun
::
clearDNSServers
(
const
QString
&
service
)
{
QProcess
process
;
process
.
start
(
"networksetup"
,
QStringList
()
<<
"-setdnsservers"
<<
service
<<
"empty"
);
if
(
!
process
.
waitForFinished
(
5000
))
{
qWarning
()
<<
"Timeout while clearing DNS for service"
<<
service
<<
":"
<<
process
.
errorString
();
return
false
;
}
}
saveCurrentConnectionInterfaceData
();
if
(
process
.
exitCode
()
!=
0
)
{
qWarning
()
<<
"Command failed for service"
<<
service
<<
"with exit code:"
<<
process
.
exitCode
();
qWarning
()
<<
"Error output: "
<<
process
.
readAllStandardError
();
return
false
;
}
// networksetup -ordernetworkservices
return
true
;
}
// Update route table for upstream if it's not local
void
DapUtun
::
clearAllDNS
()
{
if
(
!
isLocalAddress
(
upstreamAddress
()))
{
QStringList
services
=
getNetworkServices
();
QString
run
=
QString
(
"route add -host %2 %1"
)
if
(
services
.
isEmpty
())
{
.
arg
(
m_defaultGwOld
).
arg
(
upstreamAddress
());
qWarning
()
<<
"No network services to clear DNS."
;
qDebug
()
<<
"Execute "
<<
run
;
return
;
::
system
(
run
.
toLatin1
().
constData
());
}
}
// Add all CDBs into routing exeption
for
(
const
QString
&
service
:
services
)
{
for
(
const
auto
&
str
:
m_routingExceptionAddrs
){
QString
dns
=
getDNSServers
(
service
);
QString
run
=
QString
(
"route add -host %2 %1"
)
.
arg
(
m_defaultGwOld
).
arg
(
str
);
if
(
dns
.
isEmpty
()
||
dns
.
contains
(
"There aren't any DNS Servers set on"
))
{
qDebug
()
<<
"Execute "
<<
run
;
qDebug
()
<<
"DNS servers already cleared for service:"
<<
service
;
::
system
(
run
.
toLatin1
().
constData
()
);
continue
;
}
else
{
qWarning
()
<<
"Existing DNS servers for"
<<
service
<<
":"
<<
dns
;
}
if
(
clearDNSServers
(
service
))
{
dns
=
getDNSServers
(
service
);
if
(
dns
.
isEmpty
()
||
dns
.
contains
(
"There aren't any DNS Servers set on"
))
{
qDebug
()
<<
"DNS servers successfully cleared for service:"
<<
service
;
}
else
{
qWarning
()
<<
"DNS servers still present after clearance for service"
<<
service
<<
":"
<<
dns
;
}
}
}
}
}
void
DapUtun
::
onWorkerStarted
()
{
qDebug
()
<<
"Starting tunnel creation"
;
// Create connection
if
(
m_tunSocket
<=
0
)
{
/*
qCritical
()
<<
"Failed to bring up network interface: invalid tunnel socket"
;
QString cmdConnAdd = QString(
return
;
"networksetup -createnetworkservice %1 %2 ;"
}
"networksetup -setnetworkserviceenabled %1 on;"
"networksetup -setmanual %1 %3 255.255.255.255 %4;"
"networksetup -setdnsservers %4"
) .arg (DAP_BRAND)
.arg(tunDeviceName())
.arg(addr())
.arg(gw());
qDebug() << "[Cmd to created interface: " << cmdConnAdd;
saveCurrentConnectionInterfaceData
();
clearAllDNS
();
DapTunUnixAbstract::runShellCmd( cmdConnAdd );
m_currentInterface
=
getCurrentNetworkInterface
();
if
(
m_currentInterface
.
isEmpty
())
{
qCritical
()
<<
"No active network interface found!"
;
return
;
}
if
(
!
isLocalAddress
(
upstreamAddress
()))
{
QString
run
=
QString
(
"route add -host %2 %1"
)
.
arg
(
m_defaultGwOld
)
.
arg
(
upstreamAddress
());
executeCommand
(
run
);
}
// Add additional Apple routes
for
(
const
auto
&
address
:
m_routingExceptionAddrs
)
{
QString
cmdAddAdditionalRoutes = QString("networksetup -setadditionalroutes %1").arg(DAP_BRAND);
QString
run
=
QString
(
"route add -host %2 %1"
)
foreach(QString additionalRoute, appleAdditionalRoutes){
.
arg
(
m_defaultGwOld
)
cmdAddAdditionalRoutes += additionalRoute
;
.
arg
(
address
)
;
cmdAddAdditionalRoutes += "\"\""
;
executeCommand
(
run
)
;
}
}
DapTunUnixAbstract::runShellCmd( cmdAddAdditionalRoutes);*/
// QString cmdConnAdd = QString(
// "networksetup -createnetworkservice %1 %2 ;"
// "networksetup -setnetworkserviceenabled %1 on;"
// "networksetup -setmanual %1 %3 255.255.255.255 %4;"
// ).arg(DAP_BRAND)
// .arg(tunDeviceName())
// .arg(addr())
// .arg(gw());
// qDebug() << "Network service creation command:" << cmdConnAdd;
// DapUtils::shellCmd(cmdConnAdd);
// B
ring
up network interface
QSt
ring
cmdSetDNS
=
QString
(
"networksetup -setdnsservers %1 %2"
)
::
system
(
QString
(
"ifconfig %1 %2 %3"
)
.
arg
(
m_currentInterface
)
.
arg
(
tunDeviceName
()).
arg
(
addr
()).
arg
(
gw
()).
toLatin1
().
constData
());
.
arg
(
gw
());
qDebug
()
<<
"Configured "
<<
tunDeviceName
()
<<
" with "
<<
addr
()
<<
"-->"
<<
gw
();
qDebug
()
<<
"Setting DNS for"
<<
m_currentInterface
<<
"to:"
<<
gw
();
DapUtils
::
shellCmd
(
cmdSetDNS
);
// Remove old default route
QString
ifconfigCmd
=
QString
(
"ifconfig %1 %2 %3"
)
::
system
(
QString
(
"route delete default"
).
toLatin1
().
constData
());
.
arg
(
tunDeviceName
())
.
arg
(
addr
())
.
arg
(
gw
());
executeCommand
(
ifconfigCmd
);
qDebug
()
<<
"Configured interface"
<<
tunDeviceName
()
<<
"with IP"
<<
addr
()
<<
"and gateway"
<<
gw
();
qDebug
()
<<
"Removed default route "
<<
m_defaultGwOld
;
executeCommand
(
"route delete default"
);
qDebug
()
<<
"Removed default route:"
<<
m_defaultGwOld
;
// Setup default route
QString
gateway
=
gw
();
QString
gateway
=
gw
();
qDebug
()
<<
"Gateway obtained: "
<<
gateway
;
qDebug
()
<<
"Gateway obtained: "
<<
gateway
;
if
(
!
gateway
.
isEmpty
())
{
if
(
!
gateway
.
isEmpty
())
{
::
system
(
QString
(
"route add default %1"
).
arg
(
gateway
)
.
toLatin1
().
constData
()
);
executeCommand
(
QString
(
"route add default %1"
).
arg
(
gateway
));
qDebug
()
<<
"Added default route
"
<<
gateway
;
qDebug
()
<<
"Added default route
:
"
<<
gateway
;
::
system
(
QString
(
"route add -net 224.0.0.0/4 %1"
).
arg
(
gateway
)
.
toLatin1
().
constData
()
);
executeCommand
(
QString
(
"route add -net 224.0.0.0/4 %1"
).
arg
(
gateway
));
qDebug
()
<<
"Added multicast route "
<<
gateway
;
qDebug
()
<<
"Added multicast route
via gateway:
"
<<
gateway
;
::
system
(
QString
(
"route add -net 255.255.255.255/32 %1"
).
arg
(
gateway
)
.
toLatin1
().
constData
()
);
executeCommand
(
QString
(
"route add -net 255.255.255.255/32 %1"
).
arg
(
gateway
));
qDebug
()
<<
"Added broadcast route "
<<
gateway
;
qDebug
()
<<
"Added broadcast route
via gateway:
"
<<
gateway
;
}
else
{
}
else
{
qWarning
()
<<
"Gateway is empty
!
"
;
qWarning
()
<<
"Gateway is empty
, cannot set up default routes
"
;
}
}
// Add additional Apple routes
QString
cmdAddAdditionalRoutes
=
QString
(
"networksetup -setadditionalroutes %1"
).
arg
(
DAP_BRAND
);
foreach
(
QString
additionalRoute
,
appleAdditionalRoutes
)
{
foreach
(
const
QString
&
additionalRoute
,
appleAdditionalRoutes
)
{
QStringList
routeArgs
=
additionalRoute
.
split
(
QRegExp
(
"
\\
s+"
),
Qt
::
SkipEmptyParts
);
cmdAddAdditionalRoutes
+=
" "
+
additionalRoute
;
if
(
routeArgs
.
length
()
==
1
)
{
::
system
(
QString
(
"route add -host %1 %2"
)
.
arg
(
routeArgs
[
0
]).
arg
(
gw
()).
toLatin1
().
constData
());
qDebug
()
<<
"Added host route "
<<
routeArgs
[
0
]
<<
" via "
<<
gw
();
}
else
if
(
routeArgs
.
length
()
==
2
)
{
::
system
(
QString
(
"route add -net %1 %2 %3"
)
.
arg
(
routeArgs
[
0
]).
arg
(
routeArgs
[
1
]).
arg
(
gw
()).
toLatin1
().
constData
());
qDebug
()
<<
"Added network route "
<<
routeArgs
[
0
]
<<
"/"
<<
routeArgs
[
1
]
<<
" via "
<<
gw
();
}
else
{
qWarning
()
<<
"Unparseable additional route line "
<<
additionalRoute
;
}
}
}
qDebug
()
<<
"Additional Apple routes command:"
<<
cmdAddAdditionalRoutes
;
DapUtils
::
shellCmd
(
cmdAddAdditionalRoutes
);
m_isCreated
=
true
;
m_isCreated
=
true
;
emit
created
();
emit
created
();
}
}
QString
DapUtun
::
getCurrentNetworkInterface
()
{
qDebug
()
<<
"Fetching current active network interface..."
;
QProcess
routeProcess
;
routeProcess
.
start
(
"route get default"
);
routeProcess
.
waitForFinished
();
QString
routeOutput
=
routeProcess
.
readAllStandardOutput
();
qDebug
()
<<
"Raw route get default output:"
<<
routeOutput
;
QString
activeInterface
;
QStringList
routeLines
=
routeOutput
.
split
(
"
\n
"
);
for
(
const
QString
&
line
:
routeLines
)
{
if
(
line
.
contains
(
"interface:"
))
{
activeInterface
=
line
.
split
(
":"
).
last
().
trimmed
();
qDebug
()
<<
"Detected active interface:"
<<
activeInterface
;
break
;
}
}
if
(
activeInterface
.
isEmpty
())
{
qWarning
()
<<
"No active internet interface found!"
;
return
QString
();
}
QProcess
serviceOrderProcess
;
serviceOrderProcess
.
start
(
"networksetup -listnetworkserviceorder"
);
serviceOrderProcess
.
waitForFinished
();
QString
serviceOrderOutput
=
serviceOrderProcess
.
readAllStandardOutput
();
qDebug
()
<<
"Raw network service order output:"
<<
serviceOrderOutput
;
QString
regexPattern
=
R"(\(Hardware Port: (.+?), Device: )"
+
QRegularExpression
::
escape
(
activeInterface
)
+
R"(\))"
;
QRegularExpression
regex
(
regexPattern
);
QRegularExpressionMatch
match
=
regex
.
match
(
serviceOrderOutput
);
if
(
match
.
hasMatch
())
{
QString
matchedService
=
match
.
captured
(
1
).
trimmed
();
qDebug
()
<<
"Matched active network service via service order:"
<<
matchedService
;
return
matchedService
;
}
qWarning
()
<<
"Could not match active interface to a network service!"
;
return
QString
();
}
/**
* @brief DapUtun::onWorkerStopped
*/
void
DapUtun
::
tunDeviceDestroy
()
void
DapUtun
::
tunDeviceDestroy
()
{
{
DapTunUnixAbstract
::
tunDeviceDestroy
();
DapTunUnixAbstract
::
tunDeviceDestroy
();
// Delete upstream routes
if
(
!
isLocalAddress
(
upstreamAddress
()))
if
(
!
isLocalAddress
(
upstreamAddress
())){
{
QString
cmdDeleteUpstream
=
QString
(
"route delete -host %1"
)
QString
run
=
QString
(
"route delete -host %1"
)
.
arg
(
upstreamAddress
());
.
arg
(
upstreamAddress
())
;
executeCommand
(
cmdDeleteUpstream
);
qDebug
()
<<
"Execute "
<<
run
;
::
system
(
run
.
toLatin1
().
constData
()
);
}
}
for
(
const
auto
&
str
:
m_routingExceptionAddrs
){
for
(
const
auto
&
route
:
m_routingExceptionAddrs
)
{
QString
run
=
QString
(
"route delete -host %1"
)
QString
cmdDeleteException
=
QString
(
"route delete -host %1"
)
.
arg
(
str
);
.
arg
(
route
);
qDebug
()
<<
"Execute "
<<
run
;
executeCommand
(
cmdDeleteException
);
::
system
(
run
.
toLatin1
().
constData
()
);
}
}
// Other routes connected with tunnel should be destroyed autimaticly
// Other routes connected with tunnel should be destroyed autimaticly
// Restore default gateway
// Restore default gateway
::
system
(
QString
(
"route add default %1"
).
arg
(
m_defaultGwOld
).
toLatin1
().
constData
());
QString
cmdRestoreDefault
=
QString
(
"route add default %1"
)
qInfo
()
<<
"Restored default route "
<<
m_defaultGwOld
;
.
arg
(
m_defaultGwOld
);
executeCommand
(
cmdRestoreDefault
);
qInfo
()
<<
"Restored default route:"
<<
m_defaultGwOld
;
QString
cmdRestoreDNS
=
QString
(
"networksetup -setdnsservers
\"
%1
\"
%2"
)
.
arg
(
m_currentInterface
)
.
arg
(
m_defaultGwOld
);
executeCommand
(
cmdRestoreDNS
);
qInfo
()
<<
"Restored DNS settings for"
<<
m_currentInterface
<<
"to"
<<
m_defaultGwOld
;
}
}
This diff is collapsed.
Click to expand it.
vpn/client/darwin/DapUtun.h
+
33
−
1
View file @
60919b48
...
@@ -20,7 +20,28 @@ This file is part of DAP UI SDK the open source project
...
@@ -20,7 +20,28 @@ This file is part of DAP UI SDK the open source project
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#pragma once
#pragma once
#include
<QtDebug>
#include
<QProcess>
#include
<QFile>
#include
<sys/types.h>
#include
<sys/ioctl.h>
#include
<sys/socket.h>
#include
<sys/sys_domain.h>
#include
<sys/kern_control.h>
#include
<net/if_utun.h>
#include
<errno.h>
#include
<string.h>
#include
<unistd.h>
#include
<fcntl.h>
#include
"DapTunUnixAbstract.h"
#include
"DapTunWorkerUnix.h"
#include
"DapNetworkMonitor.h"
#include
"SigUnixHandler.h"
#include
"DapTunUnixAbstract.h"
#include
"DapTunUnixAbstract.h"
class
DapUtun
:
public
DapTunUnixAbstract
class
DapUtun
:
public
DapTunUnixAbstract
...
@@ -29,9 +50,13 @@ public:
...
@@ -29,9 +50,13 @@ public:
DapUtun
();
DapUtun
();
~
DapUtun
()
{}
~
DapUtun
()
{}
protected
:
protected
:
void
executeCommand
(
const
QString
&
cmd
);
void
tunDeviceCreate
();
void
tunDeviceCreate
();
void
tunDeviceDestroy
();
void
tunDeviceDestroy
();
void
onWorkerStarted
();
void
onWorkerStarted
();
void
clearAllDNS
();
QString
getCurrentNetworkInterface
();
// Getting currently using connection interface name from nmcli command-line tool
// Getting currently using connection interface name from nmcli command-line tool
// and save to m_lastUsedConnectionName and m_lastUsedConnectionDevice
// and save to m_lastUsedConnectionName and m_lastUsedConnectionDevice
...
@@ -39,14 +64,21 @@ protected:
...
@@ -39,14 +64,21 @@ protected:
private
:
private
:
QStringList
getNetworkServices
();
QString
getDNSServers
(
const
QString
&
service
);
bool
clearDNSServers
(
const
QString
&
service
);
// Connection witch used before creating utun Interface
// Connection witch used before creating utun Interface
QString
m_lastUsedConnectionName
;
QString
m_lastUsedConnectionName
;
QString
m_lastUsedConnectionDevice
;
QString
m_lastUsedConnectionDevice
;
QString
m_currentInterface
;
QStringList
appleAdditionalRoutes
;
// List of Apple addresses needed to be routed directly through the tunnel
QStringList
appleAdditionalRoutes
;
// List of Apple addresses needed to be routed directly through the tunnel
QString
runShellCmd
(
const
QString
&
cmd
);
//
QString runShellCmd(const QString& cmd);
// Get current active internet interface
// Get current active internet interface
QString
getInternetInterface
();
QString
getInternetInterface
();
};
};
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment