Skip to content

feat(network): add full IPv6 DNS support and fix persistence issues#354

Merged
robertkill merged 1 commit intolinuxdeepin:masterfrom
robertkill:master
Jun 10, 2025
Merged

feat(network): add full IPv6 DNS support and fix persistence issues#354
robertkill merged 1 commit intolinuxdeepin:masterfrom
robertkill:master

Conversation

@robertkill
Copy link
Copy Markdown
Contributor

@robertkill robertkill commented Jun 10, 2025

  • Implement IPv6 validation in NetUtils.js for DNS input fields
  • Fix backend storage in dccnetwork.cpp to use QHostAddress format
  • Add ignore-auto-dns=true setting for proper NetworkManager persistence
  • Update frontend QML components to handle mixed IPv4/IPv6 DNS
  • Enhance netmanagerthreadprivate.cpp to read IPv6 DNS from NM settings

Fixes issues with IPv6 DNS input, saving and display in Control Center.

pms: BUG-319129

Summary by Sourcery

Enable comprehensive IPv6 DNS support and persistence by updating validation, UI, backend storage, and NetworkManager settings handling

New Features:

  • Support mixed IPv4/IPv6 DNS inputs and storage in both frontend QML components and backend DccNetwork
  • Implement IPv6 validation functions in NetUtils.js to validate and differentiate IPv4 vs IPv6 addresses
  • Fetch and apply manual IPv6 gateway and DNS from NetworkManager settings in NetManagerThreadPrivate

Bug Fixes:

  • Fix persistence of custom IPv6 DNS by setting ignore-auto-dns on the IPv6 setting
  • Correct backend storage of DNS entries to use QHostAddress formats for both IPv4 and IPv6

Enhancements:

  • Merge IPv4 and IPv6 DNS entries in settings pages and separate them on save
  • Remove regex-only validation in QML and unify IP validation logic for robust IPv6 support

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

代码审查意见:

dcc-network/operation/dccnetwork.cpp:

  1. 在处理IPv6 DNS时,对于IPv6地址的日志输出应该更加详细,包括地址和协议类型,以便于调试。
  2. 在处理IPv6 DNS时,对于未实现的IPv6支持,应该抛出异常或者提供更明确的错误信息,而不是仅仅输出警告。
  3. 在处理IPv6 DNS时,应该检查系统是否支持IPv6,如果不支持,应该提供相应的错误处理或者提示。
  4. 在处理IPv6 DNS时,应该确保在系统不支持IPv6的情况下,不会尝试将IPv6地址转换为数字表示。

dcc-network/qml/NetUtils.js:

  1. isValidIpAddress函数中,应该检查IP地址的格式是否正确,而不仅仅是验证其是否为有效的IPv4或IPv6地址。
  2. isValidIpAddress函数中,应该使用正则表达式来验证IP地址的格式,而不是使用test方法。
  3. isValidIpAddress函数中,应该检查IP地址的长度是否正确,例如IPv4地址应该是4个字节,IPv6地址应该是16个字节。
  4. isValidIpAddress函数中,应该检查IP地址的每个字节是否在正确的范围内,例如0到255。

dcc-network/qml/PageDSLSettings.qml, PageSettings.qml, PageVPNSettings.qml:

  1. 在合并IPv4和IPv6的DNS配置时,应该检查IPv4和IPv6的DNS配置是否都存在,然后再进行合并。
  2. 在分离IPv4和IPv6的DNS配置时,应该检查DNS配置的类型,例如是否为数字格式或字符串格式。
  3. 在保存IPv4和IPv6的DNS配置时,应该确保IPv4和IPv6的DNS配置都正确保存,并且不会丢失任何配置信息。

dcc-network/qml/SectionDNS.qml:

  1. 在处理DNS配置时,应该检查DNS配置的类型,例如是否为数字格式或字符串格式。
  2. 在处理DNS配置时,应该确保DNS配置的格式正确,例如IPv4地址应该是4个字节,IPv6地址应该是16个字节。
  3. 在处理DNS配置时,应该检查DNS配置的每个字节是否在正确的范围内,例如0到255。
  4. 在处理DNS配置时,应该确保DNS配置的格式正确,例如IPv4地址应该是4个字节,IPv6地址应该是16个字节。

net-view/operation/private/netmanagerthreadprivate.cpp:

  1. 在获取IPv6配置时,应该检查IPv6配置的类型,例如是否为手动配置或自动配置。
  2. 在获取IPv6配置时,应该确保IPv6配置的格式正确,例如IPv4地址应该是4个字节,IPv6地址应该是16个字节。
  3. 在获取IPv6配置时,应该检查IPv6配置的每个字节是否在正确的范围内,例如0到255。
  4. 在获取IPv6配置时,应该确保IPv6配置的格式正确,例如IPv4地址应该是4个字节,IPv6地址应该是16个字节。

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Jun 10, 2025

Reviewer's Guide

This PR implements full IPv6 DNS support and fixes persistence by refactoring the back-end to consistently fetch and store IPv6 gateway and DNS via DBus, extending the dccnetwork layer to parse and persist both IPv4/IPv6 DNS addresses with ignore-auto-dns flags, and updating QML frontend (NetUtils.js, SectionDNS.qml, and page components) to validate, display, merge, and split mixed DNS entries.

Sequence Diagram for Retrieving IPv6 DNS Configuration

sequenceDiagram
    participant QMLUI as QML UI
    participant NMTP as NetManagerThreadPrivate
    participant NM as NetworkManager (DBus)

    QMLUI->>NMTP: Request Connection Info (id)
    activate NMTP
    NMTP->>NM: Call GetSettings (org.freedesktop.NetworkManager.Settings.Connection)
    activate NM
    NM-->>NMTP: Return DBusSettingsMap (with ipv6.dns as QList<QHostAddress> or StringList)
    deactivate NM
    NMTP-->>NMTP: Process response, convert IPv6 DNS to QStringList if needed
    NMTP-->>QMLUI: Emit request(NetManager::ConnectInfo, id, params_with_ipv6_dns)
    deactivate NMTP
Loading

Sequence Diagram for Setting IPv6 DNS Configuration

sequenceDiagram
    actor User
    participant PageQML as Page*.qml
    participant SectionDNSQML as SectionDNS.qml
    participant DccNetworkSvc as DccNetwork
    participant NMTP as NetManagerThreadPrivate
    participant NM as NetworkManager (DBus)

    User->>PageQML: Input/Modify DNS (IPv4/IPv6) & Save
    activate PageQML
    PageQML->>SectionDNSQML: getConfig()
    activate SectionDNSQML
    SectionDNSQML-->>PageQML: Return mixed DNS list (numbers for IPv4, strings for IPv6)
    deactivate SectionDNSQML
    PageQML-->>PageQML: Prepare nConfig (separate ipv4.dns and ipv6.dns)
    PageQML->>DccNetworkSvc: exec(NetManager.SetConnectInfo, id, nConfig)
    deactivate PageQML
    activate DccNetworkSvc
    DccNetworkSvc-->>DccNetworkSvc: Process ipv6.dns (convert to QList<QHostAddress>, then to QStringList for NM, set ignore-auto-dns=true)
    DccNetworkSvc->>NMTP: m_manager->exec(SetConnectInfo, id, processedParams)
    deactivate DccNetworkSvc
    activate NMTP
    NMTP-->>NMTP: Convert QStringList IPv6 DNS to QList<QHostAddress>
    NMTP-->>NMTP: Update Ipv6Setting (ipv6Setting->setDns(), ipv6Setting->setIgnoreAutoDns(true))
    NMTP->>NM: Update Connection Settings (via NM API)
    activate NM
    NM-->>NMTP: Settings Updated Confirmation
    deactivate NM
    NMTP-->>DccNetworkSvc: Result
    deactivate NMTP
Loading

Class Diagram for Backend C++ Components (Network IPv6 DNS Handling)

classDiagram
    class NetManagerThreadPrivate {
        <<Modified>>
        +doGetConnectInfo(const QString& id, NetType::NetItemType type) void
        +doSetConnectInfo(const QString& id, NetType::NetItemType type, const QVariantMap& param) void
    }

    class DccNetwork {
        <<Modified>>
        +exec(NetManager::CmdType cmd, const QString& id, const QVariantMap& param) void
    }

    class Ipv6Setting {
      %% NetworkManager Library Class (Conceptual)
      +setDns(QList~QHostAddress~ dns)
      +setIgnoreAutoDns(bool ignore)
      +dns() QList~QHostAddress~
      +method() Method
    }

    NetManagerThreadPrivate ..> Ipv6Setting : uses
Loading

File-Level Changes

Change Details Files
Refactor netmanagerthreadprivate.cpp to uniformly fetch and persist IPv6 gateway and DNS settings
  • Consolidated repeated DBus GetSettings calls into a common block for manual IPv6 retrieval
  • Extracted IPv6 gateway and DNS from NetworkManager settings or setting object
  • Updated retParam["ipv6"] assembly to include both gateway and DNS lists
  • Added setConnectInfo logic to convert dns strings to QHostAddress list, set ignore-auto-dns and mark initialization
net-view/operation/private/netmanagerthreadprivate.cpp
Enhance dccnetwork backend to parse and store both IPv4 and IPv6 DNS addresses
  • Support numeric and string DNS values for IPv4 and IPv6 in DNS parsing
  • Built IpV6DBusAddressList from address-data and integrated into tmpParam
  • Converted IPv6 DNS list to string list and set ignore-auto-dns flag for persistence
  • Removed ignore-auto-dns when no valid IPv6 DNS entries are provided
dcc-network/operation/dccnetwork.cpp
Add IPv6-aware validation functions in NetUtils.js and standardize variable declarations
  • Introduced isIpv4Address, isIpv6Address, and isValidIpAddress functions using regex
  • Replaced inline regex and RegularExpressionValidator with manual IP validation calls
  • Standardized var/let usage across utility functions
dcc-network/qml/NetUtils.js
Refactor SectionDNS.qml to handle mixed IPv4/IPv6 entries and manual validation
  • Supported both numeric and string DNS entries in getConfig and getConfig return list
  • Replaced regex validator with NetUtils.isValidIpAddress in checkInput and added detailed logging
  • Adjusted inputMethodHints to allow colon input and removed RegularExpressionValidator
dcc-network/qml/SectionDNS.qml
Merge and split IPv4 and IPv6 DNS arrays in QML pages for display and persistence
  • Combined config.ipv4.dns and config.ipv6.dns into a single list for initial display
  • On save, separated sectionDNS.getConfig into ipv4Dns (numbers) and ipv6Dns (strings)
  • Assigned ipv4Dns and ipv6Dns back to nConfig under respective keys for persistence
dcc-network/qml/PageDSLSettings.qml
dcc-network/qml/PageSettings.qml
dcc-network/qml/PageVPNSettings.qml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @robertkill - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • ipv6RegExp is not defined (link)

General comments:

  • There’s a lot of duplicated DBus-fetching and IPv6 mapping logic in NetManagerThreadPrivate—consider extracting that into a shared helper to reduce code duplication and simplify maintenance.
  • The backend still logs a warning for “IPv6 DNS not fully implemented”—you should implement the numeric/packed representation or define a clear fallback so users actually get full IPv6 DNS support.
  • The numerous console.log calls in NetUtils.js and QML will flood production logs—either remove them or guard them behind a debug‐mode flag.
Here's what I looked at during the review
  • 🔴 General issues: 1 blocking issue, 4 other issues
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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<QVariantMap>();
// 手动获取IPv6配置(包括gateway和DNS)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: IPv6 settings retrieval logic is duplicated

Refactor the repeated IPv6 gateway and DNS retrieval logic into a helper function for better maintainability.

Suggested implementation:

                        if (!dbusSettingsMap.isError() && dbusSettingsMap.value().contains("ipv6")) {
                            QVariantMap ipv6Data = dbusSettingsMap.value().value("ipv6");
                            QVariantMap ipv6Map = retParam["ipv6"].value<QVariantMap>();

                            // 使用辅助函数处理IPv6 gateway和DNS
                            insertIpv6GatewayAndDns(ipv6, ipv6Data, ipv6Map);
/**
 * Helper function to insert IPv6 gateway and DNS into the provided map.
 */
static void insertIpv6GatewayAndDns(const Ipv6Setting::Ptr& ipv6, const QVariantMap& ipv6Data, QVariantMap& ipv6Map)
{
    // 处理IPv6 gateway
    if (ipv6->method() == Ipv6Setting::Manual && ipv6Data.contains("gateway")) {
        QString gateway = ipv6Data.value("gateway").toString();
        ipv6Map.insert("gateway", gateway);
    }
    // 处理IPv6 DNS
    if (ipv6Data.contains("dns")) {
        QVariant dnsVariant = ipv6Data.value("dns");
        if (dnsVariant.canConvert<QVariantList>()) {
            QVariantList dnsList = dnsVariant.toList();
            ipv6Map.insert("dns", dnsList);
        }
    }
}
  • Replace any other duplicated logic for extracting IPv6 gateway and DNS elsewhere in the file with calls to insertIpv6GatewayAndDns.
  • Ensure the helper function is placed in an appropriate location (e.g., near the top of the file or in an anonymous namespace if needed).
  • If the DNS logic is more complex elsewhere, adjust the helper accordingly.

// 手动处理IPv6 DNS设置 - 确保正确初始化
if (map.contains("ipv6")) {
QVariant ipv6Variant = map["ipv6"];
if (ipv6Variant.type() == QVariant::Map) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use of QVariant::type() is deprecated

QVariant::type() is deprecated in Qt 6. Use QVariant::userType() or canConvert()/toMap with appropriate checks instead.

dns.append(addr.toIPv4Address());
} else if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
// IPv6地址转换为128位表示(当前系统可能不支持,先跳过)
qWarning() << "IPv6 DNS not fully implemented in backend, DNS:" << dnsStr;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: IPv6 DNS handling is unimplemented and skipped

If IPv6 DNS support is needed, please implement full handling or add a fallback to avoid skipped records.

Comment thread dcc-network/qml/NetUtils.js Outdated

// 验证IP地址是否为IPv6
function isIpv6Address(ip) {
var result = ipv6RegExp.test(ip)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): ipv6RegExp is not defined

This will cause a runtime error. Please define or import ipv6RegExp.

Comment on lines +156 to +160
// 移除正则验证器,改用手动验证以支持IPv6
// 显式允许所有字符输入,包括冒号
inputMethodHints: Qt.ImhNone
onTextChanged: {
console.log("[DNS-Input] Text changed in DNS field", index, ":", text)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Removing validator may hurt user experience

Disabling input method hints removes the numeric keypad for IPv4 entry. Dynamically set hints based on the input type (IPv4 or IPv6) to maintain optimal user experience.

Suggested change
// 移除正则验证器,改用手动验证以支持IPv6
// 显式允许所有字符输入,包括冒号
inputMethodHints: Qt.ImhNone
onTextChanged: {
console.log("[DNS-Input] Text changed in DNS field", index, ":", text)
// 移除正则验证器,改用手动验证以支持IPv6
// 根据输入内容动态设置 inputMethodHints:IPv4 用数字键盘,IPv6/其他用默认键盘
inputMethodHints: {
// 简单判断:只包含数字和点,认为是 IPv4
if (/^[0-9.]*$/.test(text)) {
return Qt.ImhDigitsOnly
}
// 其他情况(如包含冒号等),允许所有字符
return Qt.ImhNone
}
onTextChanged: {
console.log("[DNS-Input] Text changed in DNS field", index, ":", text)

Comment thread dcc-network/qml/NetUtils.js Outdated
let num = parseInt(octet, 10)
for (var j = 0; j < octets.length; j++) {
var octet = octets[j]
var num = parseInt(octet, 10)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

Comment thread dcc-network/qml/NetUtils.js Outdated
return new Uint8Array(hexArr.match(/[\da-f]{2}/gi).map(bb => {
return parseInt(bb, 16)
})).buffer
var arr = str.split(":")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

Comment thread dcc-network/qml/NetUtils.js Outdated
return parseInt(bb, 16)
})).buffer
var arr = str.split(":")
var hexArr = arr.join("")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

Comment thread dcc-network/qml/NetUtils.js Outdated
var arr = []
for (var i = 0; i < data.length; ++i) {
let charcode = data.charCodeAt(i)
var charcode = data.charCodeAt(i)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

Comment thread dcc-network/qml/NetUtils.js Outdated
return new Uint8Array(arr).buffer
} else if (data instanceof ArrayBuffer) {
const uint8Array = new Uint8Array(data)
var uint8Array = new Uint8Array(data)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Use const or let instead of var. (avoid-using-var)

Explanation`const` is preferred as it ensures you cannot reassign references (which can lead to buggy and confusing code). `let` may be used if you need to reassign references - it's preferred to `var` because it is block- rather than function-scoped.

From the Airbnb JavaScript Style Guide

- Implement IPv6 validation in NetUtils.js for DNS input fields
- Fix backend storage in dccnetwork.cpp to use QHostAddress format
- Add ignore-auto-dns=true setting for proper NetworkManager persistence
- Update frontend QML components to handle mixed IPv4/IPv6 DNS
- Enhance netmanagerthreadprivate.cpp to read IPv6 DNS from NM settings

Fixes issues with IPv6 DNS input, saving and display in Control Center.

pms: BUG-319129
@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: caixr23, robertkill

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@robertkill robertkill merged commit 5b61e04 into linuxdeepin:master Jun 10, 2025
15 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants