diff --git a/dcc-network/operation/dccnetwork.cpp b/dcc-network/operation/dccnetwork.cpp index 35a3a90b..756f6c82 100644 --- a/dcc-network/operation/dccnetwork.cpp +++ b/dcc-network/operation/dccnetwork.cpp @@ -65,32 +65,92 @@ void DccNetwork::exec(NetManager::CmdType cmd, const QString &id, const QVariant const QVariantList &dnsData = ipData.value("dns").toList(); QList dns; for (auto it : dnsData) { - dns.append(it.toUInt()); + // 支持两种DNS格式:数字格式(IPv4)和字符串格式(IPv6) + if (it.type() == QVariant::UInt || it.type() == QVariant::Int) { + dns.append(it.toUInt()); + } else if (it.type() == QVariant::String) { + QString dnsStr = it.toString(); + if (!dnsStr.isEmpty()) { + // IPv6地址需要通过QHostAddress转换为数字表示 + QHostAddress addr(dnsStr); + if (addr.protocol() == QAbstractSocket::IPv4Protocol) { + // IPv4字符串转换为数字 + dns.append(addr.toIPv4Address()); + } else if (addr.protocol() == QAbstractSocket::IPv6Protocol) { + // IPv6地址转换为128位表示(当前系统可能不支持,先跳过) + qWarning() << "IPv6 DNS not fully implemented in backend, DNS:" << dnsStr; + // 这里需要实现IPv6 DNS的完整支持 + } + } + } } ipData["dns"] = QVariant::fromValue(dns); } tmpParam["ipv4"] = QVariant::fromValue(ipData); } - if (param.contains("ipv6") && param.value("ipv6").toMap().contains("address-data")) { - const QVariantList &addressData = param.value("ipv6").toMap().value("address-data").toList(); - QString gatewayStr = param.value("ipv6").toMap().value("gateway").toString(); - IpV6DBusAddressList ipv6AddressList; - for (auto it : addressData) { - IpV6DBusAddress ipv6Address; - QVariantMap ipv6Data = it.toMap(); - QHostAddress ip(ipv6Data.value("address").toString()); - QIPv6Address ipv6Addr = ip.toIPv6Address(); - QByteArray tmpAddress((char *)(ipv6Addr.c), 16); - ipv6Address.address = tmpAddress; - ipv6Address.prefix = ipv6Data.value("prefix").toUInt(); - QHostAddress gateway(ipv6AddressList.isEmpty() ? gatewayStr : QString()); - QByteArray tmpGateway((char *)(gateway.toIPv6Address().c), 16); - ipv6Address.gateway = tmpGateway; - ipv6AddressList.append(ipv6Address); + if (param.contains("ipv6")) { + QVariantMap ipv6Data = param.value("ipv6").toMap(); + + // 处理IPv6地址 + if (ipv6Data.contains("address-data")) { + const QVariantList &addressData = ipv6Data.value("address-data").toList(); + QString gatewayStr = ipv6Data.value("gateway").toString(); + IpV6DBusAddressList ipv6AddressList; + for (auto it : addressData) { + IpV6DBusAddress ipv6Address; + QVariantMap ipv6AddrData = it.toMap(); + QHostAddress ip(ipv6AddrData.value("address").toString()); + QIPv6Address ipv6Addr = ip.toIPv6Address(); + QByteArray tmpAddress((char *)(ipv6Addr.c), 16); + ipv6Address.address = tmpAddress; + ipv6Address.prefix = ipv6AddrData.value("prefix").toUInt(); + QHostAddress gateway(ipv6AddressList.isEmpty() ? gatewayStr : QString()); + QByteArray tmpGateway((char *)(gateway.toIPv6Address().c), 16); + ipv6Address.gateway = tmpGateway; + ipv6AddressList.append(ipv6Address); + } + ipv6Data["addresses"] = QVariant::fromValue(ipv6AddressList); + } + + // 处理IPv6 DNS + if (ipv6Data.contains("dns")) { + const QVariantList &dnsData = ipv6Data.value("dns").toList(); + QList ipv6DnsAddresses; + for (auto it : dnsData) { + if (it.type() == QVariant::String) { + QString dnsStr = it.toString(); + if (!dnsStr.isEmpty()) { + QHostAddress addr(dnsStr); + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { + ipv6DnsAddresses.append(addr); + } + } + } + } + if (!ipv6DnsAddresses.isEmpty()) { + // 直接使用字符串列表格式 - NetworkManager配置文件实际存储字符串 + QStringList ipv6DnsStrings; + for (const QHostAddress &addr : ipv6DnsAddresses) { + ipv6DnsStrings.append(addr.toString()); + } + + // 使用字符串列表格式保存IPv6 DNS + ipv6Data["dns"] = ipv6DnsStrings; + ipv6Data["ignore-auto-dns"] = true; + } else { + // 没有有效的IPv6 DNS时,确保移除ignore-auto-dns设置 + // 这样系统可以恢复自动获取DNS + ipv6Data.remove("dns"); + ipv6Data.remove("ignore-auto-dns"); + } + + // 确保IPv6设置存在,即使没有DNS也要设置,以便被正确处理 + if (ipv6Data.isEmpty()) { + ipv6Data["method"] = "auto"; // 至少设置一个值确保IPv6部分存在 + } } - QVariantMap ipData = param.value("ipv6").toMap(); - ipData["addresses"] = QVariant::fromValue(ipv6AddressList); - tmpParam["ipv6"] = QVariant::fromValue(ipData); + + tmpParam["ipv6"] = QVariant::fromValue(ipv6Data); } m_manager->exec(cmd, id, tmpParam); } break; diff --git a/dcc-network/qml/NetUtils.js b/dcc-network/qml/NetUtils.js index f72d4137..4cf9c183 100644 --- a/dcc-network/qml/NetUtils.js +++ b/dcc-network/qml/NetUtils.js @@ -19,14 +19,37 @@ const maskRegExp = /(254|252|248|240|224|192|128|0)\.0\.0\.0|255\.(254|252|248|2 // MAC正则表达式 const macRegExp = /([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})/ +// 验证IP地址是否为IPv4 +function isIpv4Address(ip) { + const result = ipRegExp.test(ip) + console.log("[IPv4-Validation] Validating IPv4:", ip, "Result:", result) + return result +} + +// 验证IP地址是否为IPv6 +function isIpv6Address(ip) { + const result = ipv6RegExp.test(ip) + console.log("[IPv6-Validation] Validating IPv6:", ip, "Result:", result) + return result +} + +// 验证IP地址(同时支持IPv4和IPv6) +function isValidIpAddress(ip) { + const ipv4Result = isIpv4Address(ip) + const ipv6Result = isIpv6Address(ip) + const finalResult = ipv4Result || ipv6Result + console.log("[IP-Validation] Validating IP:", ip, "IPv4:", ipv4Result, "IPv6:", ipv6Result, "Final:", finalResult) + return finalResult +} + function toVpnTypeEnum(vpnKey) { - let key = vpnKey.substring(31) + const key = vpnKey.substring(31) console.log("toVpnTypeEnum", vpnKey, key) return VpnTypeEnum.hasOwnProperty(key) ? VpnTypeEnum[key] : 0x01 } function toVpnKey(vpnType) { - for (let key in VpnTypeEnum) { + for (const key in VpnTypeEnum) { if (VpnTypeEnum[key] === vpnType) { return "org.freedesktop.NetworkManager." + key } @@ -39,8 +62,8 @@ function removeTrailingNull(str) { } function numToIp(num) { - let ips = [0, 0, 0, 0] - for (var i = 0; i < 4; i++) { + const ips = [0, 0, 0, 0] + for (let i = 0; i < 4; i++) { ips[i] = (num >> (i * 8)) & 255 } return ips.join('.') @@ -48,14 +71,15 @@ function numToIp(num) { function ipToNum(ip) { console.log("ipToNum----", ip, typeof ip) - let ips = ip.split('.') + const ips = ip.split('.') let cidr = 0 let ipNum = 0 if (ips.length !== 4) { return 0 } - for (let ipStr of ips) { - let num = parseInt(ipStr, 10) + for (let i = 0; i < ips.length; i++) { + const ipStr = ips[i] + const num = parseInt(ipStr, 10) ipNum |= ((num & 255) << cidr) cidr += 8 } @@ -67,10 +91,10 @@ function prefixToIp(subnetMask) { throw new Error("Subnet mask must be between 0 and 32") } - let maskArray = [255, 255, 255, 255] + const maskArray = [255, 255, 255, 255] - for (var i = 0; i < 4; i++) { - let byteBits = i * 8 + 8 - subnetMask + for (let i = 0; i < 4; i++) { + const byteBits = i * 8 + 8 - subnetMask if (byteBits > 0) { maskArray[i] = (255 << byteBits) & 255 } @@ -80,12 +104,13 @@ function prefixToIp(subnetMask) { } function ipToPrefix(decimalSubnet) { - let octets = decimalSubnet.split('.') + const octets = decimalSubnet.split('.') let cidr = 0 - for (let octet of octets) { - let num = parseInt(octet, 10) - for (var i = 0; i < 8; i++) { + for (let j = 0; j < octets.length; j++) { + const octet = octets[j] + const num = parseInt(octet, 10) + for (let i = 0; i < 8; i++) { if ((num & (1 << (7 - i))) !== 0) { cidr++ } else { @@ -99,22 +124,26 @@ function ipToPrefix(decimalSubnet) { } function macToStr(mac) { - return Array.prototype.map.call(new Uint8Array(mac), x => ('00' + x.toString(16)).toUpperCase().slice(-2)).join(':') + return Array.prototype.map.call(new Uint8Array(mac), function(x) { + return ('00' + x.toString(16)).toUpperCase().slice(-2) + }).join(':') } + function strToMac(str) { if (str.length === 0) return new Uint8Array() - let arr = str.split(":") - let hexArr = arr.join("") - return new Uint8Array(hexArr.match(/[\da-f]{2}/gi).map(bb => { - return parseInt(bb, 16) - })).buffer + const arr = str.split(":") + const hexArr = arr.join("") + return new Uint8Array(hexArr.match(/[\da-f]{2}/gi).map(function(bb) { + return parseInt(bb, 16) + })).buffer } + // 转为ByteArray并以\0结尾 function strToByteArray(data) { if (typeof data === 'string') { - var arr = [] - for (var i = 0; i < data.length; ++i) { + const arr = [] + for (let i = 0; i < data.length; ++i) { let charcode = data.charCodeAt(i) if (charcode < 0x80) { arr.push(charcode) @@ -125,7 +154,7 @@ function strToByteArray(data) { } else { // Handle surrogate pairs (U+10000 to U+10FFFF) i++ - charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff)) + charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (data.charCodeAt(i) & 0x3ff)) arr.push(0xf0 | (charcode >> 18), 0x80 | ((charcode >> 12) & 0x3f), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)) } } diff --git a/dcc-network/qml/PageDSLSettings.qml b/dcc-network/qml/PageDSLSettings.qml index a520757e..c668605b 100644 --- a/dcc-network/qml/PageDSLSettings.qml +++ b/dcc-network/qml/PageDSLSettings.qml @@ -73,7 +73,15 @@ DccObject { sectionGeneric.setConfig(config.connection) sectionPPPOE.setConfig(config["pppoe"]) sectionIPv4.setConfig(config.ipv4) - sectionDNS.setConfig((config.hasOwnProperty("ipv4") && config.ipv4.hasOwnProperty("dns")) ? config.ipv4.dns : null) + // 合并IPv4和IPv6的DNS配置 + let combinedDns = [] + if (config.hasOwnProperty("ipv4") && config.ipv4.hasOwnProperty("dns") && config.ipv4.dns.length > 0) { + combinedDns = combinedDns.concat(config.ipv4.dns) + } + if (config.hasOwnProperty("ipv6") && config.ipv6.hasOwnProperty("dns") && config.ipv6.dns.length > 0) { + combinedDns = combinedDns.concat(config.ipv6.dns) + } + sectionDNS.setConfig(combinedDns.length > 0 ? combinedDns : null) sectionDevice.setConfig(config["802-3-ethernet"]) sectionPPP.setConfig(config["ppp"]) modified = config.connection.uuid === "{00000000-0000-0000-0000-000000000000}" @@ -192,7 +200,32 @@ DccObject { if (nConfig["ipv4"] === undefined) { nConfig["ipv4"] = {} } - nConfig["ipv4"]["dns"] = sectionDNS.getConfig() + + // 获取DNS配置并分离IPv4和IPv6 + let dnsConfig = sectionDNS.getConfig() + let ipv4Dns = [] + let ipv6Dns = [] + + for (let dns of dnsConfig) { + if (typeof dns === 'number') { + // IPv4 DNS(数字格式) + ipv4Dns.push(dns) + } else if (typeof dns === 'string') { + // IPv6 DNS(字符串格式) + ipv6Dns.push(dns) + } + } + + // 保存IPv4 DNS + nConfig["ipv4"]["dns"] = ipv4Dns + + // 如果有IPv6 DNS,也要保存 + if (ipv6Dns.length > 0) { + if (!nConfig["ipv6"]) { + nConfig["ipv6"] = {} + } + nConfig["ipv6"]["dns"] = ipv6Dns + } let devConfig = sectionDevice.getConfig() if (devConfig.interfaceName.length !== 0) { nConfig["pppoe"]["parent"] = devConfig.interfaceName diff --git a/dcc-network/qml/PageSettings.qml b/dcc-network/qml/PageSettings.qml index 2f8f623b..ff1d63ae 100644 --- a/dcc-network/qml/PageSettings.qml +++ b/dcc-network/qml/PageSettings.qml @@ -76,7 +76,15 @@ DccObject { sectionSecret.setConfig802_1x(config["802-1x"]) sectionIPv4.setConfig(config.ipv4) sectionIPv6.setConfig(config.ipv6) - sectionDNS.setConfig((config.hasOwnProperty("ipv4") && config.ipv4.hasOwnProperty("dns")) ? config.ipv4.dns : null) + // 合并IPv4和IPv6的DNS配置 + let combinedDns = [] + if (config.hasOwnProperty("ipv4") && config.ipv4.hasOwnProperty("dns") && config.ipv4.dns.length > 0) { + combinedDns = combinedDns.concat(config.ipv4.dns) + } + if (config.hasOwnProperty("ipv6") && config.ipv6.hasOwnProperty("dns") && config.ipv6.dns.length > 0) { + combinedDns = combinedDns.concat(config.ipv6.dns) + } + sectionDNS.setConfig(combinedDns.length > 0 ? combinedDns : null) sectionDevice.type = type sectionDevice.setConfig(config[config.connection.type]) modified = config.connection.uuid === "{00000000-0000-0000-0000-000000000000}" && sectionGeneric.settingsID.length !== 0 @@ -197,7 +205,28 @@ DccObject { if (nConfig["ipv4"] === undefined) { nConfig["ipv4"] = {} } - nConfig["ipv4"]["dns"] = sectionDNS.getConfig() + if (nConfig["ipv6"] === undefined) { + nConfig["ipv6"] = {} + } + + // 获取DNS配置并分离IPv4和IPv6 + let dnsConfig = sectionDNS.getConfig() + let ipv4Dns = [] + let ipv6Dns = [] + + for (let dns of dnsConfig) { + if (typeof dns === 'number') { + // IPv4 DNS(数字格式) + ipv4Dns.push(dns) + } else if (typeof dns === 'string') { + // IPv6 DNS(字符串格式) + ipv6Dns.push(dns) + } + } + + // 分别保存到IPv4和IPv6配置中 + nConfig["ipv4"]["dns"] = ipv4Dns + nConfig["ipv6"]["dns"] = ipv6Dns let devConfig = sectionDevice.getConfig() if (devConfig.interfaceName.length === 0) { delete nConfig["connection"]["interface-name"] diff --git a/dcc-network/qml/PageVPNSettings.qml b/dcc-network/qml/PageVPNSettings.qml index 420574c6..4b390af7 100644 --- a/dcc-network/qml/PageVPNSettings.qml +++ b/dcc-network/qml/PageVPNSettings.qml @@ -30,7 +30,15 @@ DccObject { sectionVPN.setConfig(config["vpn"]) sectionIPv4.setConfig(config.ipv4) sectionIPv6.setConfig(config.ipv6) - sectionDNS.setConfig((config.hasOwnProperty("ipv4") && config.ipv4.hasOwnProperty("dns")) ? config.ipv4.dns : null) + // 合并IPv4和IPv6的DNS配置 + let combinedDns = [] + if (config.hasOwnProperty("ipv4") && config.ipv4.hasOwnProperty("dns") && config.ipv4.dns.length > 0) { + combinedDns = combinedDns.concat(config.ipv4.dns) + } + if (config.hasOwnProperty("ipv6") && config.ipv6.hasOwnProperty("dns") && config.ipv6.dns.length > 0) { + combinedDns = combinedDns.concat(config.ipv6.dns) + } + sectionDNS.setConfig(combinedDns.length > 0 ? combinedDns : null) modified = config.connection.uuid === "{00000000-0000-0000-0000-000000000000}" if (c.check && (!sectionGeneric.checkInput() || !sectionVPN.checkInput() || !sectionIPv4.checkInput() || !sectionIPv6.checkInput() || !sectionDNS.checkInput())) { @@ -279,7 +287,28 @@ DccObject { if (nConfig["ipv4"] === undefined) { nConfig["ipv4"] = {} } - nConfig["ipv4"]["dns"] = sectionDNS.getConfig() + if (nConfig["ipv6"] === undefined) { + nConfig["ipv6"] = {} + } + + // 获取DNS配置并分离IPv4和IPv6 + let dnsConfig = sectionDNS.getConfig() + let ipv4Dns = [] + let ipv6Dns = [] + + for (let dns of dnsConfig) { + if (typeof dns === 'number') { + // IPv4 DNS(数字格式) + ipv4Dns.push(dns) + } else if (typeof dns === 'string') { + // IPv6 DNS(字符串格式) + ipv6Dns.push(dns) + } + } + + // 分别保存到IPv4和IPv6配置中 + nConfig["ipv4"]["dns"] = ipv4Dns + nConfig["ipv6"]["dns"] = ipv6Dns nConfig["vpn"]["service-type"] = NetUtils.toVpnKey(vpnType) if (item) { dccData.exec(NetManager.SetConnectInfo, item.id, nConfig) diff --git a/dcc-network/qml/SectionDNS.qml b/dcc-network/qml/SectionDNS.qml index 651d788d..7679096c 100644 --- a/dcc-network/qml/SectionDNS.qml +++ b/dcc-network/qml/SectionDNS.qml @@ -28,8 +28,13 @@ DccObject { let tmpConfig = [] for (var i in c) { if (c[i] !== 0) { - let ip = NetUtils.numToIp(c[i]) - tmpConfig.push(ip) + // 支持两种格式:数字格式(旧的IPv4)和字符串格式(新的IPv4/IPv6) + if (typeof c[i] === 'number') { + let ip = NetUtils.numToIp(c[i]) + tmpConfig.push(ip) + } else if (typeof c[i] === 'string' && c[i].length > 0) { + tmpConfig.push(c[i]) + } } } while (tmpConfig.length < 2) { @@ -39,24 +44,66 @@ DccObject { } } function getConfig() { - let saveData = [] + console.log("[DNS-GetConfig] Starting DNS config processing, raw config:", root.config) + let ipv4Data = [] + let ipv6Data = [] + for (var ip of root.config) { - let ipNum = NetUtils.ipToNum(ip) - if (ipNum !== 0) { - saveData.push(ipNum) + if (ip !== "") { + console.log("[DNS-GetConfig] Processing IP:", ip) + // 检查是否为有效的IP地址(IPv4或IPv6) + if (NetUtils.isValidIpAddress(ip)) { + if (NetUtils.isIpv4Address(ip)) { + // IPv4 DNS保存为数字格式 + let ipNum = NetUtils.ipToNum(ip) + console.log("[DNS-GetConfig] IPv4 processed:", ip, "->", ipNum) + if (ipNum !== 0) { + ipv4Data.push(ipNum) + } + } else if (NetUtils.isIpv6Address(ip)) { + // IPv6 DNS保存为字符串格式 + console.log("[DNS-GetConfig] IPv6 processed:", ip) + ipv6Data.push(ip) + } + } else { + console.log("[DNS-GetConfig] Invalid IP address:", ip) + } + } else { + console.log("[DNS-GetConfig] Empty IP skipped") } } + + // 返回混合数据,后端会根据类型分别处理 + let saveData = [] + for (let ipv4 of ipv4Data) { + saveData.push(ipv4) + } + for (let ipv6 of ipv6Data) { + saveData.push(ipv6) + } + + console.log("[DNS-GetConfig] Final save data:", saveData, "IPv4:", ipv4Data, "IPv6:", ipv6Data) return saveData } function checkInput() { + console.log("[DNS-Check] Starting DNS validation, config:", root.config) errorKey = "" for (var i in root.config) { - if (root.config[i] !== "" && !NetUtils.ipRegExp.test(root.config[i])) { - errorKey = "dns" + i - return false + if (root.config[i] !== "") { + console.log("[DNS-Check] Validating DNS entry", i, ":", root.config[i]) + if (!NetUtils.isValidIpAddress(root.config[i])) { + console.log("[DNS-Check] Validation failed for DNS entry", i, ":", root.config[i]) + errorKey = "dns" + i + return false + } else { + console.log("[DNS-Check] Validation passed for DNS entry", i, ":", root.config[i]) + } + } else { + console.log("[DNS-Check] Empty DNS entry", i, "skipped") } } + console.log("[DNS-Check] All DNS entries validated successfully") return true } @@ -106,14 +153,16 @@ DccObject { page: RowLayout { D.LineEdit { text: root.config[index] - validator: RegularExpressionValidator { - regularExpression: NetUtils.ipRegExp - } + // 移除正则验证器,改用手动验证以支持IPv6 + // 显式允许所有字符输入,包括冒号 + inputMethodHints: Qt.ImhNone onTextChanged: { + console.log("[DNS-Input] Text changed in DNS field", index, ":", text) if (showAlert) { errorKey = "" } if (text !== root.config[index]) { + console.log("[DNS-Input] Updating config[" + index + "] from", root.config[index], "to", text) root.config[index] = text root.editClicked() } diff --git a/net-view/operation/private/netmanagerthreadprivate.cpp b/net-view/operation/private/netmanagerthreadprivate.cpp index 40fd2b28..f6e9df0f 100644 --- a/net-view/operation/private/netmanagerthreadprivate.cpp +++ b/net-view/operation/private/netmanagerthreadprivate.cpp @@ -1065,16 +1065,42 @@ void NetManagerThreadPrivate::doGetConnectInfo(const QString &id, NetType::NetIt Ipv6Setting::Ptr ipv6 = connectionSettings->setting(Setting::Ipv6).dynamicCast(); connection->path(); - if (ipv6->method() == Ipv6Setting::Manual) { - // ipv6 gateway未获取,自己获取下 - auto msg = QDBusMessage::createMethodCall("org.freedesktop.NetworkManager", connection->path(), "org.freedesktop.NetworkManager.Settings.Connection", "GetSettings"); - QDBusPendingReply settingsMap = QDBusConnection::systemBus().call(msg, QDBus::Block, 100); - if (!settingsMap.isError() && settingsMap.value().contains("ipv6") && settingsMap.value().value("ipv6").contains("gateway")) { - QString gateway = settingsMap.value().value("ipv6").value("gateway").toString(); - QVariantMap ipv6Map = retParam["ipv6"].value(); + // 手动获取IPv6配置(包括gateway和DNS) + auto msg = QDBusMessage::createMethodCall("org.freedesktop.NetworkManager", connection->path(), "org.freedesktop.NetworkManager.Settings.Connection", "GetSettings"); + QDBusPendingReply dbusSettingsMap = QDBusConnection::systemBus().call(msg, QDBus::Block, 100); + if (!dbusSettingsMap.isError() && dbusSettingsMap.value().contains("ipv6")) { + QVariantMap ipv6Data = dbusSettingsMap.value().value("ipv6"); + QVariantMap ipv6Map = retParam["ipv6"].value(); + + // 处理IPv6 gateway + if (ipv6->method() == Ipv6Setting::Manual && ipv6Data.contains("gateway")) { + QString gateway = ipv6Data.value("gateway").toString(); ipv6Map.insert("gateway", gateway); - retParam["ipv6"] = ipv6Map; } + + // 处理IPv6 DNS - 首先从NetworkManager设置中直接读取 + const QList &ipv6DnsFromSettings = ipv6->dns(); + if (!ipv6DnsFromSettings.isEmpty()) { + QStringList dnsStringList; + for (const QHostAddress &dns : ipv6DnsFromSettings) { + dnsStringList.append(dns.toString()); + } + ipv6Map.insert("dns", dnsStringList); + } else if (ipv6Data.contains("dns")) { + QVariantList dnsConfig = ipv6Data.value("dns").toList(); + QStringList ipv6DnsList; + for (const QVariant &dns : dnsConfig) { + QString dnsStr = dns.toString(); + if (!dnsStr.isEmpty()) { + ipv6DnsList.append(dnsStr); + } + } + if (!ipv6DnsList.isEmpty()) { + ipv6Map.insert("dns", ipv6DnsList); + } + } + + retParam["ipv6"] = ipv6Map; } Q_EMIT request(NetManager::ConnectInfo, id, retParam); @@ -1150,16 +1176,42 @@ void NetManagerThreadPrivate::doGetConnectInfo(const QString &id, NetType::NetIt retParam[settingsMap["connection"]["type"].toString()] = typeMap; Ipv6Setting::Ptr ipv6 = settings->setting(Setting::Ipv6).dynamicCast(); - if (ipv6->method() == Ipv6Setting::Manual) { - // ipv6 gateway未获取,自己获取下 - QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.NetworkManager", con->path(), "org.freedesktop.NetworkManager.Settings.Connection", "GetSettings"); - QDBusPendingReply settingsMap = QDBusConnection::systemBus().call(msg, QDBus::Block, 100); - if (!settingsMap.isError() && settingsMap.value().contains("ipv6") && settingsMap.value().value("ipv6").contains("gateway")) { - QString gateway = settingsMap.value().value("ipv6").value("gateway").toString(); - QVariantMap ipv6Map = retParam["ipv6"].value(); + // 手动获取IPv6配置(包括gateway和DNS) + QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.NetworkManager", con->path(), "org.freedesktop.NetworkManager.Settings.Connection", "GetSettings"); + QDBusPendingReply dbusSettingsReply = QDBusConnection::systemBus().call(msg, QDBus::Block, 100); + if (!dbusSettingsReply.isError() && dbusSettingsReply.value().contains("ipv6")) { + QVariantMap ipv6Data = dbusSettingsReply.value().value("ipv6"); + QVariantMap ipv6Map = retParam["ipv6"].value(); + + // 处理IPv6 gateway + if (ipv6->method() == Ipv6Setting::Manual && ipv6Data.contains("gateway")) { + QString gateway = ipv6Data.value("gateway").toString(); ipv6Map.insert("gateway", gateway); - retParam["ipv6"] = ipv6Map; } + + // 处理IPv6 DNS - 首先从NetworkManager设置中直接读取 + const QList &ipv6DnsFromSettings = ipv6->dns(); + if (!ipv6DnsFromSettings.isEmpty()) { + QStringList dnsStringList; + for (const QHostAddress &dns : ipv6DnsFromSettings) { + dnsStringList.append(dns.toString()); + } + ipv6Map.insert("dns", dnsStringList); + } else if (ipv6Data.contains("dns")) { + QVariantList dnsConfig = ipv6Data.value("dns").toList(); + QStringList ipv6DnsList; + for (const QVariant &dns : dnsConfig) { + QString dnsStr = dns.toString(); + if (!dnsStr.isEmpty()) { + ipv6DnsList.append(dnsStr); + } + } + if (!ipv6DnsList.isEmpty()) { + ipv6Map.insert("dns", ipv6DnsList); + } + } + + retParam["ipv6"] = ipv6Map; } Q_EMIT request(NetManager::ConnectInfo, id, retParam); @@ -1435,6 +1487,38 @@ void NetManagerThreadPrivate::doSetConnectInfo(const QString &id, NetType::NetIt pSetting->setParent(map["pppoe"]["parent"].toString()); pSetting->setInitialized(true); } + + // 手动处理IPv6 DNS设置 - 确保正确初始化 + if (map.contains("ipv6")) { + QVariant ipv6Variant = map["ipv6"]; + if (ipv6Variant.type() == QVariant::Map) { + QVariantMap ipv6Map = ipv6Variant.toMap(); + if (ipv6Map.contains("dns")) { + QVariant dnsVariant = ipv6Map["dns"]; + if (dnsVariant.type() == QVariant::StringList) { + QStringList ipv6DnsStrings = dnsVariant.toStringList(); + if (!ipv6DnsStrings.isEmpty()) { + NetworkManager::Ipv6Setting::Ptr ipv6Setting = settings->setting(Setting::SettingType::Ipv6).staticCast(); + + // 转换字符串列表为QHostAddress列表 + QList ipv6DnsAddresses; + for (const QString &dnsStr : ipv6DnsStrings) { + QHostAddress addr(dnsStr); + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { + ipv6DnsAddresses.append(addr); + } + } + + if (!ipv6DnsAddresses.isEmpty()) { + ipv6Setting->setDns(ipv6DnsAddresses); + ipv6Setting->setIgnoreAutoDns(true); + ipv6Setting->setInitialized(true); // 关键!确保设置被初始化 + } + } + } + } + } + } NetworkManager::Connection::Ptr connection; if (settings->uuid() == "{00000000-0000-0000-0000-000000000000}") { // 新增