From patchwork Fri Jul 28 13:12:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lev Stipakov X-Patchwork-Id: 3306 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7301:3787:b0:d7:3b0f:3938 with SMTP id jw7csp576866dyb; Fri, 28 Jul 2023 06:18:59 -0700 (PDT) X-Google-Smtp-Source: APBJJlExe3tjxiL6L4klq06b1Q0wcEhfsZhSFgrr9P2oUVKH731eLxqcgE6bCRcuNktDLwgdvQ3f X-Received: by 2002:a17:902:f547:b0:1ba:fe63:6616 with SMTP id h7-20020a170902f54700b001bafe636616mr1574609plf.6.1690550339546; Fri, 28 Jul 2023 06:18:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1690550339; cv=none; d=google.com; s=arc-20160816; b=J38Hky1+wjoWzZA+zzNTy+MIE0mo7Sae5cV+/wWjR6ugOY2LMNEYHRqteJaosHKcae H6pth2pXC+LA8rfczb935gSeHot2SBOiQahv3i8LLI8c3WWBbEpGNSZ/edTEEvhrWX29 PNTx9Ejw6QK0u74SgihaywDTWc7xFC1NwHWOlJSL1S2X3MoYOqT1ZNkgY1N947RdYD/g xp0CP5uvym54D6weniZfR0Un6H45htAlO9xIRPjwC5nbJyldka7JlaUVKxXl7d/gjRyQ W0po5FR0WTgQvdrTmHodI44x2U97AAPcONieOtFy4vvTgM9R6IaE1d02+00UM5/C2LGf zn1Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:cc:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:date:to:from:dkim-signature:dkim-signature :dkim-signature; bh=9Hg3XXhiCLMjyJ+if1Iyr6Ku7acfNqT85xlyH5u/5P4=; fh=o9LvTEhp9Htq5/McLoxX/vV+8wLprJRMAMA6oYFIWDY=; b=PAXK0nSEKtZqIq5PXXV2LED3fb+Nds3dlJQrjYORaV3ejv179tAxxerSekUZb527kD 8Thc5y1oUpiBLOzWWuUoW/XtjVs+ieMz/2+4x6/8MaYdmb49hTX6cXQ2hl7kX7onBf8N v+KMzNTf1+CwzSKzUElr3HM6HxO4KXJgOmDZPGcK1gNdSDho8k9TsmVtwAYqX+lQzj70 CBVDjz+fcNLAUJZh6C1c/Owj+BdBFv50rBJw94qgMCiO6Mm1jQ5D96rZ5YXzdXToqmUc Lr9HGleddXp0iopRWPfSZfvNhcox44RqtPlBXNC9hsFsqD5hGu7Qj2pVuz/l5I+2TPR9 ZXRg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=c6WppwNc; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Gfyjwb5O; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20221208 header.b=nDRgHQCN; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id z16-20020a170903019000b001b8b37f0ab0si3141490plg.280.2023.07.28.06.18.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 28 Jul 2023 06:18:59 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=c6WppwNc; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Gfyjwb5O; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20221208 header.b=nDRgHQCN; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1qPNMd-0002DT-Gk; Fri, 28 Jul 2023 13:18:39 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1qPNMc-0002DM-3o for openvpn-devel@lists.sourceforge.net; Fri, 28 Jul 2023 13:18:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=bFqXImjICnbongnDAX39tuy49hxU8ZmUQGDLA9/y0Q4=; b=c6WppwNceh9hG9xW+Orzvq+TvD P92LHmpu7g0POhboNmJ5swNNjEE6pzEkfRjgNtjAHciAVLD5JZJ55YnPuAYx7Akql7XwlM/lmweK0 WCvw/TqLbOeWFgzOmpvGjH8zfARf9LPosYiafH9gWVowsrWZYX2CbLnB4iFcYRcUTxpk=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=bFqXImjICnbongnDAX39tuy49hxU8ZmUQGDLA9/y0Q4=; b=G fyjwb5OA0ku7l5YKA9FlmivnJ5lwfHMudT2/tzR1BJ6vdWBBTENlYoActhwaXq7gKPTILJn/4cXMs GFcbEU0yOaua2XRdcfhCgC6IjHN/YIi9WmnJk3b0RcJ6RfpbCvBxyPhp9FcDTZK/rVtKrVSBTqD+l Cpf4c/c753BlJiW4=; Received: from mail-lj1-f182.google.com ([209.85.208.182]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1qPNMY-005XGv-2k for openvpn-devel@lists.sourceforge.net; Fri, 28 Jul 2023 13:18:38 +0000 Received: by mail-lj1-f182.google.com with SMTP id 38308e7fff4ca-2b9540031acso34399071fa.3 for ; Fri, 28 Jul 2023 06:18:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1690550307; x=1691155107; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=bFqXImjICnbongnDAX39tuy49hxU8ZmUQGDLA9/y0Q4=; b=nDRgHQCNxikSi2FWZ6R9KThCKI4InunzYwM/G16j/3AQRoNywfTLVvRfy/7qokC5Wr aPisIvEPy/QhEI5i9h1D33i/OkpblM4BV1VXGTIhYkFVicREIDq0Acvnu3xzkiK3qqu/ o5fHbBIY1X33qypMZuieNOcFZtPW6KGi7yGT/qZPOiqv7edaEEesHUmR3XTYHCYPsTDM HtKictV0E1iDHENdhdS75XoV/5T1WNY+m8ILnRNXifcGaJgB6Fq2qNI6SgvVBSjen8xZ oKPhWe1qmnGbwjVecUk+r8iJJmth0xVV3jliTATDUbZ6NISEknhrByo48VBDjrFmGsEn z55w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690550307; x=1691155107; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=bFqXImjICnbongnDAX39tuy49hxU8ZmUQGDLA9/y0Q4=; b=AGWEFTJD32/E4VezlQVf1dV/wZEV/iadeSuM9aiFibSJW69CqGZ5uL6xTCB7sTCbhF 2w3rcQflUxBJKQG1JtOT85LUi2LlBQSYXXrP6fpZdP/0fOpbUCAsauAIM5uAdoX6Dt4T /CiFBZDxRS4+LS6K6p6dPf2N3syjr298BLwwqT+Z1iZIbHGwREBjnc80E/H5hbvA+x44 /7Zmna9JTeoEI/ETWcVjL4MVir3il2W5jdiH11l9UAH3F/8s0Dkt0MF3ITFqTITFnmLN dPy0Cc9XgPqJty7XUI2uoUqKqqd56g4OAN+tK6TeI8TxxVWTiTEtwGDUSoDYsMmYrO6u mZEw== X-Gm-Message-State: ABy/qLYGi0G/St9IiMdEENtag33g/UoyKWl3cHn0AvQXqRJjhQVypjIg w2lCN6p2vIC2xTQVmiV34iPL6Rh9WWWuwA== X-Received: by 2002:a2e:8544:0:b0:2b9:c5ca:a423 with SMTP id u4-20020a2e8544000000b002b9c5caa423mr1842094ljj.18.1690549980890; Fri, 28 Jul 2023 06:13:00 -0700 (PDT) Received: from localhost.localdomain ([213.139.161.186]) by smtp.gmail.com with ESMTPSA id e9-20020a2e9309000000b002b6cdbd9e35sm938696ljh.55.2023.07.28.06.13.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 28 Jul 2023 06:13:00 -0700 (PDT) From: Lev Stipakov To: openvpn-devel@lists.sourceforge.net Date: Fri, 28 Jul 2023 16:12:46 +0300 Message-Id: <20230728131246.694-1-lstipakov@gmail.com> X-Mailer: git-send-email 2.23.0.windows.1 MIME-Version: 1.0 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Lev Stipakov At the moments WINS servers are set either: - via DHCP, which works only for tap-windows6 driver - via netsh when running without interactice service Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [lstipakov[at]gmail.com] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.208.182 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.208.182 listed in wl.mailspike.net] -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1qPNMY-005XGv-2k Subject: [Openvpn-devel] [PATCH] Set WINS servers via interactice service X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lev Stipakov Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1772670512513388516?= X-GMAIL-MSGID: =?utf-8?q?1772670512513388516?= From: Lev Stipakov At the moments WINS servers are set either: - via DHCP, which works only for tap-windows6 driver - via netsh when running without interactice service This means that in 2.6 default setup (interactive service and dco) WINS is silently ignored. Add WINS support for non-DHCP drivers (like dco) by passing WINS settings to interactive service and set them there with netsh call, similar approach as we use for setting DNS. Fixes https://github.com/OpenVPN/openvpn/issues/373 Change-Id: I47c22dcb728011dcedaae47cd03a57219e9c7607 Signed-off-by: Lev Stipakov --- include/openvpn-msg.h | 11 ++- src/openvpn/tun.c | 68 ++++++++++++++ src/openvpnserv/interactive.c | 162 ++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+), 1 deletion(-) diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h index 8cd26319..a1464cd1 100644 --- a/include/openvpn-msg.h +++ b/include/openvpn-msg.h @@ -40,7 +40,9 @@ typedef enum { msg_register_dns, msg_enable_dhcp, msg_register_ring_buffers, - msg_set_mtu + msg_set_mtu, + msg_add_wins_cfg, + msg_del_wins_cfg } message_type_t; typedef struct { @@ -86,6 +88,13 @@ typedef struct { inet_address_t addr[4]; /* support up to 4 dns addresses */ } dns_cfg_message_t; +typedef struct { + message_header_t header; + interface_t iface; + int addr_len; + inet_address_t addr[4]; /* support up to 4 dns addresses */ +} wins_cfg_message_t; + typedef struct { message_header_t header; interface_t iface; diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index d1fd6def..00e01d40 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -279,6 +279,72 @@ out: return ret; } +static bool +do_wins_service(bool add, const struct tuntap *tt) +{ + bool ret = false; + ack_message_t ack; + struct gc_arena gc = gc_new(); + HANDLE pipe = tt->options.msg_channel; + int len = tt->options.wins_len; + int addr_len = add ? len : 0; + + if (addr_len == 0 && add) /* no addresses to add */ + { + return true; + } + + wins_cfg_message_t wins = { + .header = { + (add ? msg_add_wins_cfg : msg_del_wins_cfg), + sizeof(wins_cfg_message_t), + 0 + }, + .iface = {.index = tt->adapter_index, .name = "" }, + .addr_len = addr_len + }; + + /* interface name is required */ + strncpy(wins.iface.name, tt->actual_name, sizeof(wins.iface.name)); + wins.iface.name[sizeof(wins.iface.name) - 1] = '\0'; + + if (addr_len > _countof(wins.addr)) + { + addr_len = _countof(wins.addr); + wins.addr_len = addr_len; + msg(M_WARN, "Number of WINS addresses sent to service truncated to %d", + addr_len); + } + + for (int i = 0; i < addr_len; ++i) + { + wins.addr[i].ipv4.s_addr = htonl(tt->options.wins[i]); + } + + msg(D_LOW, "%s WINS servers on '%s' (if_index = %d) using service", + (add ? "Setting" : "Deleting"), wins.iface.name, wins.iface.index); + + if (!send_msg_iservice(pipe, &wins, sizeof(wins), &ack, "TUN")) + { + goto out; + } + + if (ack.error_number != NO_ERROR) + { + msg(M_WARN, "TUN: %s WINS failed using service: %s [status=%u if_name=%s]", + (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc), + ack.error_number, wins.iface.name); + goto out; + } + + msg(M_INFO, "WINS servers %s using service", (add ? "set" : "deleted")); + ret = true; + +out: + gc_free(&gc); + return ret; +} + static bool do_set_mtu_service(const struct tuntap *tt, const short family, const int mtu) { @@ -1555,6 +1621,7 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu, do_address_service(true, AF_INET, tt); do_dns_service(true, AF_INET, tt); do_dns_domain_service(true, tt); + do_wins_service(true, tt); } else { @@ -6977,6 +7044,7 @@ close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx) } else if (tt->options.msg_channel) { + do_wins_service(false, tt); do_dns_domain_service(false, tt); do_dns_service(false, AF_INET, tt); do_address_service(false, AF_INET, tt); diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c index d73cef04..6c54e62b 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -93,6 +93,7 @@ typedef enum { undo_dns6, undo_domain, undo_ring_buffer, + undo_wins, _undo_type_max } undo_type_t; typedef list_item_t *undo_lists_t[_undo_type_max]; @@ -1083,6 +1084,63 @@ out: return err; } +/** + * Run the command: netsh interface ip $action wins $if_name [static] $addr + * @param action "delete" or "add" + * @param if_name "name_of_interface" + * @param addr IPv4 address as a string + * + * If addr is null and action = "delete" all addresses are deleted. + * if action = "set" then "static" is added before $addr + */ +static DWORD +netsh_wins_cmd(const wchar_t *action, const wchar_t *if_name, const wchar_t *addr) +{ + DWORD err = 0; + int timeout = 30000; /* in msec */ + wchar_t argv0[MAX_PATH]; + wchar_t *cmdline = NULL; + bool add = wcscmp(action, L"set") == 0; + const wchar_t *addr_static = add ? L"static" : L""; + + if (!addr) + { + if (!add) + { + addr = L"all"; + } + else /* nothing to do -- return success*/ + { + goto out; + } + } + + /* Path of netsh */ + openvpn_swprintf(argv0, _countof(argv0), L"%ls\\%ls", get_win_sys_path(), L"netsh.exe"); + + /* cmd template: + * netsh interface ip $action wins $if_name $static $addr + */ + const wchar_t *fmt = L"netsh interface ip %ls wins \"%ls\" %ls %ls"; + + /* max cmdline length in wchars -- include room for worst case and some */ + size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + wcslen(addr_static) + 32 + 1; + cmdline = malloc(ncmdline * sizeof(wchar_t)); + if (!cmdline) + { + err = ERROR_OUTOFMEMORY; + goto out; + } + + openvpn_swprintf(cmdline, ncmdline, fmt, action, if_name, addr_static, addr); + + err = ExecCommand(argv0, cmdline, timeout); + +out: + free(cmdline); + return err; +} + /** * Run command: wmic nicconfig (InterfaceIndex=$if_index) call $action ($data) * @param if_index "index of interface" @@ -1129,6 +1187,20 @@ wmic_nicconfig_cmd(const wchar_t *action, const NET_IFINDEX if_index, return err; } +/* Delete all WINS servers for an interface */ +static DWORD +DeleteWINS(wchar_t *if_name) +{ + return netsh_wins_cmd(L"delete", if_name, NULL); +} + +/* Add WINS server to an interface */ +static DWORD +AddWINS(wchar_t *if_name, wchar_t *addr) +{ + return netsh_wins_cmd(L"set", if_name, addr); +} + /* Delete all IPv4 or IPv6 dns servers for an interface */ static DWORD DeleteDNS(short family, wchar_t *if_name) @@ -1298,6 +1370,86 @@ out: return err; } +static DWORD +HandleWINSConfigMessage(const wins_cfg_message_t *msg, undo_lists_t *lists) +{ + DWORD err = 0; + wchar_t addr[16]; /* large enough to hold string representation of an ipv4 */ + int addr_len = msg->addr_len; + + /* sanity check */ + if (addr_len > _countof(msg->addr)) + { + addr_len = _countof(msg->addr); + } + + if (!msg->iface.name[0]) /* interface name is required */ + { + return ERROR_MESSAGE_DATA; + } + + /* use a non-const reference with limited scope to enforce null-termination of strings from client */ + { + wins_cfg_message_t *msgptr = (wins_cfg_message_t *)msg; + msgptr->iface.name[_countof(msg->iface.name) - 1] = '\0'; + } + + wchar_t *wide_name = utf8to16(msg->iface.name); /* utf8 to wide-char */ + if (!wide_name) + { + return ERROR_OUTOFMEMORY; + } + + /* We delete all current addresses before adding any + * OR if the message type is del_wins_cfg + */ + if (addr_len > 0 || msg->header.type == msg_del_wins_cfg) + { + err = DeleteWINS(wide_name); + if (err) + { + goto out; + } + free(RemoveListItem(&(*lists)[undo_wins], CmpWString, wide_name)); + } + + if (msg->header.type == msg_del_wins_cfg) + { + goto out; /* job done */ + } + + for (int i = 0; i < addr_len; ++i) + { + RtlIpv4AddressToStringW(&msg->addr[i].ipv4, addr); + err = AddWINS(wide_name, addr); + if (i == 0 && err) + { + goto out; + } + /* We do not check for duplicate addresses, so any error in adding + * additional addresses is ignored. + */ + } + + err = 0; + + if (msg->addr_len > 0) + { + wchar_t *tmp_name = _wcsdup(wide_name); + if (!tmp_name || AddListItem(&(*lists)[undo_wins], tmp_name)) + { + free(tmp_name); + DeleteWINS(wide_name); + err = ERROR_OUTOFMEMORY; + goto out; + } + } + +out: + free(wide_name); + return err; +} + static DWORD HandleEnableDHCPMessage(const enable_dhcp_message_t *dhcp) { @@ -1487,6 +1639,7 @@ HandleMessage(HANDLE pipe, HANDLE ovpn_proc, enable_dhcp_message_t dhcp; register_ring_buffers_message_t rrb; set_mtu_message_t mtu; + wins_cfg_message_t wins; } msg; ack_message_t ack = { .header = { @@ -1547,6 +1700,11 @@ HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ack.error_number = HandleDNSConfigMessage(&msg.dns, lists); break; + case msg_add_wins_cfg: + case msg_del_wins_cfg: + ack.error_number = HandleWINSConfigMessage(&msg.wins, lists); + break; + case msg_enable_dhcp: if (msg.header.size == sizeof(msg.dhcp)) { @@ -1608,6 +1766,10 @@ Undo(undo_lists_t *lists) DeleteDNS(AF_INET6, item->data); break; + case undo_wins: + DeleteWINS(item->data); + break; + case undo_domain: SetDNSDomain(item->data, "", NULL); break;