This commit is contained in:
ksn 2021-09-24 11:39:32 +08:00
commit 7c2ecb35ed
10 changed files with 212 additions and 44 deletions

14
debian/kylin-nm.postinst vendored Normal file
View File

@ -0,0 +1,14 @@
#!/bin/sh
set -e
PROGRAM=$(dpkg-divert --truename /usr/bin/kylin-nm)
if setcap cap_net_raw+ep $PROGRAM; then
chmod u-s $PROGRAM
fi
echo "kylin nm set cap success"
exit(0)

View File

@ -8,6 +8,7 @@ HEADERS += \
$$PWD/ksimplenm.h \
$$PWD/kylin-dbus-interface.h \
$$PWD/kylin-network-interface.h \
$$PWD/kylinarping.h \
$$PWD/kylinipv4arping.h \
$$PWD/kylinipv6arping.h \
$$PWD/sysdbusregister.h \

101
src/backend/kylinarping.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef KYLINARPING_H
#define KYLINARPING_H
#include <sys/capability.h>
#include <sys/prctl.h>
#include <QDebug>
static cap_flag_value_t cap_raw = CAP_CLEAR;
static const cap_value_t caps[] = { CAP_NET_RAW };
static void limit_capabilities()
{
cap_t cap_p;
cap_p = cap_get_proc();
if (!cap_p) {
qWarning()<<"cap_get_proc failed.";
}
cap_get_flag(cap_p, CAP_NET_RAW, CAP_PERMITTED, &cap_raw);
if (cap_raw != CAP_CLEAR) {
if (cap_clear(cap_p) < 0) {
qWarning()<<"cap clear failed"<<errno;
}
cap_set_flag(cap_p, CAP_PERMITTED, 1, caps, CAP_SET);
if (cap_set_proc(cap_p) < 0) {
qWarning()<<"cap set proc failed" << errno;
}
}
if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
qWarning()<<"pr set keepcaps 1 failed"<<errno;
}
if (setuid(getuid()) < 0) {
qWarning()<<"set uid failed"<< errno;
}
if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
qWarning()<<"pr set keepcaps 0 failed" << errno;
}
cap_free(cap_p);
}
static int modify_capability_raw(int on)
{
cap_t cap_p;
if (cap_raw != CAP_SET) {
qWarning()<<"modify on"<<on;
return on ? -1 : 0;
}
cap_p = cap_get_proc();
if (!cap_p) {
qWarning()<<"modify cap raw get proc failed"<<errno;
return -1;
}
cap_set_flag(cap_p, CAP_EFFECTIVE, 1, caps, on ? CAP_SET : CAP_CLEAR);
if (cap_set_proc(cap_p) < 0) {
qWarning()<<"modify cap raw set proc failed"<<errno;
}
cap_free(cap_p);
return 0;
}
static void drop_capabilities(void)
{
#if 0
cap_t cap_p = cap_init();
if (!cap_p) {
qWarning()<<"cap init failed"<<errno;
}
if (cap_set_proc(cap_p) < 0) {
qWarning()<<"drop cap set cap failed" << errno;
}
cap_free(cap_p);
#endif
}
static inline int enable_capability_raw()
{
return modify_capability_raw(1);
}
static inline int disable_capability_raw()
{
return modify_capability_raw(0);
}
#endif // KYLINARPING_H

View File

@ -375,13 +375,17 @@ void KyIpv4Arping::findBroadcastAddress()
int KyIpv4Arping::ipv4ConflictCheck()
{
limit_capabilities();
int ret = checkDevice();
if (ret < 0) {
qWarning()<<"[KyIpv4Arping]"<<"the device is invalid" << m_ifaceName;
return -1;
}
enable_capability_raw();
m_ipv4Socket = socket(PF_PACKET, SOCK_DGRAM, 0);
disable_capability_raw();
if (m_ipv4Socket < 0) {
qWarning()<<"[KyIpv4Arping]" << "create ipv4 socket failed, errno" << errno;
return -1;
@ -419,6 +423,8 @@ int KyIpv4Arping::ipv4ConflictCheck()
findBroadcastAddress();
drop_capabilities();
ret = ipv4EventLoop();
close(m_ipv4Socket);

View File

@ -20,7 +20,7 @@
#include <sys/signalfd.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include "kylinarping.h"
#include <QString>
#include <QDebug>

View File

@ -3,6 +3,7 @@
#include <sys/times.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include "kylinarping.h"
KyIpv6Arping::KyIpv6Arping(QString ifaceName, QString ipAddress, int retryCount, int timeout, QObject *parent) : QObject(parent)
{
@ -310,7 +311,11 @@ int KyIpv6Arping::ipv6ConflictCheck()
struct icmp6_filter filter;
int retry = 0;
limit_capabilities();
enable_capability_raw();
m_ipv6Socket = socket (PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
disable_capability_raw();
if (m_ipv6Socket < 0) {
qDebug()<<"[KyIpv6Arping]" <<"create ipv6 socket failed:";
return -1;
@ -321,6 +326,8 @@ int KyIpv6Arping::ipv6ConflictCheck()
/* set ICMPv6 filter */
ICMP6_FILTER_SETBLOCKALL (&filter);
ICMP6_FILTER_SETPASS (ND_NEIGHBOR_ADVERT, &filter);
enable_capability_raw();
setsockopt (m_ipv6Socket, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof (filter));
int soDontRoute = 1;
@ -339,6 +346,10 @@ int KyIpv6Arping::ipv6ConflictCheck()
setsockopt(m_ipv6Socket, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
&recvHopLimit, sizeof (recvHopLimit));
disable_capability_raw();
drop_capabilities();
/* resolves target's IPv6 address */
int ret = getIpv6ByName(&tgt);
if (ret < 0) {

View File

@ -21,30 +21,21 @@ LanPage::LanPage(QWidget *parent) : TabPage(parent)
m_activeResourse = new KyActiveConnectResourse(this);
m_connectResourse = new KyConnectResourse(this);
m_device = new KyNetworkDeviceResourse(this);
// m_nullLanItem = new LanListItem();
m_devList.empty();
initDeviceState();
initUI();
if (QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA)) {
m_switchGsettings = new QGSettings(GSETTINGS_SCHEMA);
initNetSwitch();
} else {
qDebug()<<"[LanPage] org.ukui.kylin-nm.switch is not installed!";
}
// initDeviceCombox();
initNetSwitch();
initDeviceCombox();
initList(m_deviceName);
connect(m_activeResourse, &KyActiveConnectResourse::stateChangeReason, this, &LanPage::updateLanlist);
connect(m_connectResourse, &KyConnectResourse::connectionAdd, this, &LanPage::addConnectionSlot);
connect(m_connectResourse, &KyConnectResourse::connectionRemove, this, &LanPage::removeConnectionSlot);
connect(m_connectResourse, &KyConnectResourse::connectionUpdate, this, &LanPage::connectionUpdateSlot);
// connect(m_connectResourse, &KyConnectResourse::connectionUpdate, this, &LanPage::onLanDataChange);
connect(m_device, &KyNetworkDeviceResourse::deviceAdd, this, &LanPage::onDeviceAdd);
connect(m_device, &KyNetworkDeviceResourse::deviceRemove, this, &LanPage::onDeviceRemove);
connect(m_device, &KyNetworkDeviceResourse::deviceNameUpdate, this, &LanPage::onDeviceNameUpdate);
@ -58,14 +49,34 @@ LanPage::~LanPage()
}
void LanPage::initDeviceState()
{
QMap<QString, bool> deviceStateMap;
getDeviceEnableState(WIRED, deviceStateMap);
KyWiredConnectOperation wiredOperation;
QMap<QString, bool>::iterator iter = deviceStateMap.begin();
while (iter != deviceStateMap.end()) {
if (!iter.value()) {
wiredOperation.closeWiredNetworkWithDevice(iter.key());
}
iter++;
}
}
void LanPage::initNetSwitch()
{
if (m_switchGsettings->keys().contains(WIRED_SWITCH)) {
m_netSwitch->setSwitchStatus(m_switchGsettings->get(WIRED_SWITCH).toBool());
initDeviceCombox();
connect(m_switchGsettings, &QGSettings::changed, this, &LanPage::onSwithGsettingsChanged);
if (QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA)) {
m_switchGsettings = new QGSettings(GSETTINGS_SCHEMA);
if (m_switchGsettings->keys().contains(WIRED_SWITCH)) {
m_netSwitch->setSwitchStatus(m_switchGsettings->get(WIRED_SWITCH).toBool());
connect(m_switchGsettings, &QGSettings::changed, this, &LanPage::onSwithGsettingsChanged);
}
connect(m_netSwitch, &SwitchButton::clicked, this, &LanPage::onLanSwitchClicked);
} else {
qDebug()<<"[LanPage] org.ukui.kylin-nm.switch is not installed!";
}
connect(m_netSwitch, &SwitchButton::clicked, this, &LanPage::onLanSwitchClicked);
}
void LanPage::onSwithGsettingsChanged(const QString &key)
@ -73,20 +84,26 @@ void LanPage::onSwithGsettingsChanged(const QString &key)
if (key == WIRED_SWITCH) {
m_netSwitch->blockSignals(true);
qDebug()<<"[LanPage] SwitchButton statue changed to ::" <<m_switchGsettings->get(WIRED_SWITCH).toBool();
qDebug()<<"[LanPage] SwitchButton statue changed to:"
<< m_switchGsettings->get(WIRED_SWITCH).toBool();
KyWiredConnectOperation wiredOperation;
QStringList deviceList;
m_device->getNetworkDeviceList(NetworkManager::Device::Type::Ethernet, deviceList);
bool isOn = m_switchGsettings->get(WIRED_SWITCH).toBool();
if (isOn) {
for (int index = 0; index < m_devList.size(); ++index) {
qDebug()<<"[LanPage] open wired device "<< m_devList.at(index);
wiredOperation.openWiredNetworkWithDevice(m_devList.at(index));
for (int index = 0; index < deviceList.size(); ++index) {
qDebug()<<"[LanPage] open wired device "<< deviceList.at(index);
wiredOperation.openWiredNetworkWithDevice(deviceList.at(index));
saveDeviceEnableState(deviceList.at(index), true);
}
} else {
for (int index = 0; index < m_devList.size(); ++index) {
qDebug()<<"[LanPage] close wired device "<< m_devList.at(index);
wiredOperation.closeWiredNetworkWithDevice(m_devList.at(index));
for (int index = 0; index < deviceList.size(); ++index) {
qDebug()<<"[LanPage] close wired device "<< deviceList.at(index);
wiredOperation.closeWiredNetworkWithDevice(deviceList.at(index));
saveDeviceEnableState(deviceList.at(index), false);
}
}
initDeviceCombox();
@ -100,9 +117,9 @@ void LanPage::onLanSwitchClicked()
qDebug()<<"[LanPage] On lan switch button clicked! Status:" <<m_netSwitch->getSwitchStatus();
if (m_netSwitch->getSwitchStatus()) {
m_switchGsettings->set(WIRED_SWITCH,true);
m_switchGsettings->set(WIRED_SWITCH, true);
} else {
m_switchGsettings->set(WIRED_SWITCH,false);
m_switchGsettings->set(WIRED_SWITCH, false);
}
}
@ -162,7 +179,6 @@ void LanPage::addConnectionSlot(QString uuid) //新增一个有线
addNewItem(newItem, m_inactivatedLanListWidget);
m_deactiveMap.insert(newItem, m_listWidgetItem);
}
} else {
qDebug()<<"[LanPage] GetConnectionItemByUuid is empty when add a new!";
}
@ -173,7 +189,6 @@ void LanPage::initDeviceCombox()
//TODO 获取设备列表,单设备时隐藏下拉框,多设备时添加到下拉框;m_devList记录插入的所有设备deviceMap记录设备状态
disconnect(m_deviceComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LanPage::onDeviceComboxIndexChanged);
QMap<QString, bool> deviceMap;
getDeviceEnableState(0,deviceMap);
m_deviceComboBox->clear();
m_devList.clear();
@ -184,6 +199,12 @@ void LanPage::initDeviceCombox()
return;
}
m_deviceComboBox->clear();
m_devList.clear();
enableDevice.clear();
getDeviceEnableState(WIRED, deviceMap);
bool isOn = m_switchGsettings->get(WIRED_SWITCH).toBool();
if (!isOn) {
m_deviceFrame->hide();
@ -191,6 +212,7 @@ void LanPage::initDeviceCombox()
m_inactivatedNetFrame->hide();
m_activatedNetDivider->hide();
m_inactivatedNetDivider->hide();
m_deviceName = "";
} else {
m_device->getNetworkDeviceList(NetworkManager::Device::Type::Ethernet, m_devList);
for (int i=0; i<m_devList.size(); ++i) {
@ -203,6 +225,7 @@ void LanPage::initDeviceCombox()
enableDevice << m_devList.at(i);
}
}
qDebug() << "[LanPage]device num:" << enableDevice.count();
if (enableDevice.count() == 0) {
m_deviceFrame->show();
@ -212,12 +235,15 @@ void LanPage::initDeviceCombox()
m_inactivatedNetFrame->hide();
m_activatedNetDivider->hide();
m_inactivatedNetDivider->hide();
m_deviceName = "";
return;
}
m_activatedNetFrame->show();
m_inactivatedNetFrame->show();
m_activatedNetDivider->show();
m_inactivatedNetDivider->show();
if (enableDevice.count() == 1) {
m_deviceFrame->hide();
m_deviceName = enableDevice.at(0);
@ -228,14 +254,15 @@ void LanPage::initDeviceCombox()
m_deviceFrame->show();
m_tipsLabel->hide();
m_deviceComboBox->show();
for (int j=0; j<enableDevice.count(); ++j) {
m_deviceComboBox->addItem(enableDevice.at(j));
}
}
qDebug() << "[LanPage]Current device:" << m_deviceComboBox->currentText();
m_deviceName = m_deviceComboBox->currentText();
initList(m_deviceName);
qDebug() << "[LanPage]Current device:" << m_deviceComboBox->currentText();
m_deviceName = m_deviceComboBox->currentText();
initList(m_deviceName);
}
}
connect(m_deviceComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LanPage::onDeviceComboxIndexChanged);
}
@ -351,15 +378,16 @@ void LanPage::addNewItem(KyConnectItem *itemData, QListWidget *listWidget)
// listWidget->addItem(m_listWidgetItem);
listWidget->insertItem(0,m_listWidgetItem);
LanListItem *p_lanItem = nullptr;
if (itemData != nullptr) {
m_testLanItem = new LanListItem(itemData, m_deviceName);
p_lanItem = new LanListItem(itemData, m_deviceName);
qDebug() << "[LanPage] addNewItem, connection: " << itemData->m_connectName << "deviceName: " << m_deviceName;
}
else {
m_testLanItem = new LanListItem();
p_lanItem = new LanListItem();
qDebug() << "[LanPage] Add nullItem!";
}
listWidget->setItemWidget(m_listWidgetItem, m_testLanItem);
listWidget->setItemWidget(m_listWidgetItem, p_lanItem);
}
void LanPage::initList(QString m_deviceName) //程序拉起,初始化显示
@ -530,8 +558,7 @@ void LanPage::updateLanlist(QString uuid, NetworkManager::ActiveConnection::Stat
break;
}
}
}
else{
} else {
}
@ -675,13 +702,15 @@ void LanPage::connectionUpdateSlot(QString uuid)
void LanPage::setWiredDeviceEnable(const QString& devName, bool enable)
{
saveDeviceEnableState(devName, enable);
initDeviceCombox();
KyWiredConnectOperation wiredOperation;
if (enable) {
wiredOperation.openWiredNetworkWithDevice(devName);
} else {
wiredOperation.closeWiredNetworkWithDevice(devName);
}
initDeviceCombox();
}
void LanPage::activateWired(const QString& devName, const QString& connUuid)
@ -713,11 +742,14 @@ void LanPage::showDetailPage(QString devName, QString uuid)
{
KyConnectItem *item = nullptr;
bool isActive = true;
item = m_activeResourse->getActiveConnectionByUuid(uuid, devName);
if (nullptr == item) {
item = m_connectResourse->getConnectionItemByUuid(uuid, devName);
if (nullptr == item) {
qWarning()<<"[LanPage] GetConnectionItemByUuid is empty when showDetailPage";
qWarning()<<"[LanPage] GetConnectionItemByUuid is empty when showDetailPage."
<<"device name"<<devName
<<"connect uuid"<<uuid;
return;
}
isActive= false;
@ -725,6 +757,7 @@ void LanPage::showDetailPage(QString devName, QString uuid)
NetDetail *netDetail = new NetDetail(devName, item->m_connectName, uuid, isActive, false, false, this);
netDetail->show();
delete item;
item = nullptr;
}

View File

@ -29,13 +29,16 @@ public:
void deactivateWired(const QString& devName, const QString& connUuid);
void showDetailPage(QString devName, QString uuid);
void setWiredDeviceEnable(const QString& devName, bool enable);
signals:
void lanAdd(QString devName, QStringList info);
void lanRemove(QString dbusPath);
void lanUpdate(QString devName, QStringList info);
void lanActiveConnectionStateChanged(QString interface, QString uuid, int status);
void lanConnectChanged();
private:
void initDeviceState();
void initDeviceCombox();
void initUI();
void initList(QString m_deviceName);
@ -48,7 +51,6 @@ private:
QListWidget * m_inactivatedLanListWidget = nullptr;
LanListItem * m_nullLanItem = nullptr;
LanListItem * m_testLanItem = nullptr;
QListWidgetItem *m_nullItem = nullptr;
QListWidgetItem *m_listWidgetItem = nullptr;

View File

@ -86,7 +86,7 @@ int main(int argc, char *argv[])
// QApplication a(argc, argv);
QString id = QString("kylin-nm"+ QLatin1String(getenv("DISPLAY")));
QtSingleApplication a(id, argc, argv);
// qInstallMessageHandler(messageOutput);
qInstallMessageHandler(messageOutput);
if (a.isRunning()) {
auto connection = QDBusConnection::sessionBus();
QDBusInterface iface("com.kylin.network",

View File

@ -17,7 +17,7 @@ CONFIG += qt warn_on
#CONFIG += release
CONFIG += link_pkgconfig
PKGCONFIG +=gio-2.0 glib-2.0 gio-unix-2.0 libnm libnma libsecret-1 gtk+-3.0 gsettings-qt
PKGCONFIG +=gio-2.0 glib-2.0 gio-unix-2.0 libnm libnma libsecret-1 gtk+-3.0 gsettings-qt libcap
INCLUDEPATH += /usr/include/KF5/NetworkManagerQt