Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2224424/?format=api
{ "id": 2224424, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2224424/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openwrt/patch/20260417115912.3219321-1-erik.r.karlsson@gmail.com/", "project": { "id": 45, "url": "http://patchwork.ozlabs.org/api/1.2/projects/45/?format=api", "name": "OpenWrt development", "link_name": "openwrt", "list_id": "openwrt-devel.lists.openwrt.org", "list_email": "openwrt-devel@lists.openwrt.org", "web_url": "http://openwrt.org/", "scm_url": "git://git.openwrt.org/openwrt.git", "webscm_url": "https://dev.openwrt.org/browser", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260417115912.3219321-1-erik.r.karlsson@gmail.com>", "list_archive_url": null, "date": "2026-04-17T11:59:12", "name": "[mdnsd] dns: support additional section and SRV/TXT queries", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "abd74ee101ab95ddbc9d77f04cf6b28e91da2186", "submitter": { "id": 82056, "url": "http://patchwork.ozlabs.org/api/1.2/people/82056/?format=api", "name": "Erik Karlsson", "email": "erik.r.karlsson@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/openwrt/patch/20260417115912.3219321-1-erik.r.karlsson@gmail.com/mbox/", "series": [ { "id": 500314, "url": "http://patchwork.ozlabs.org/api/1.2/series/500314/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openwrt/list/?series=500314", "date": "2026-04-17T11:59:12", "name": "[mdnsd] dns: support additional section and SRV/TXT queries", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/500314/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2224424/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2224424/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=TG9tyj+8;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=AwxL7w15;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fxtlk6bSfz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Apr 2026 22:01:54 +1000 (AEST)", "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1wDhrw-000000040Ow-1Y7U;\n\tFri, 17 Apr 2026 12:00:20 +0000", "from mail-lf1-x12f.google.com ([2a00:1450:4864:20::12f])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1wDhrt-000000040OA-0G67\n\tfor openwrt-devel@lists.openwrt.org;\n\tFri, 17 Apr 2026 12:00:18 +0000", "by mail-lf1-x12f.google.com with SMTP id\n 2adb3069b0e04-5a2c9c5ff87so762807e87.0\n for <openwrt-devel@lists.openwrt.org>;\n Fri, 17 Apr 2026 05:00:16 -0700 (PDT)", "from erik-ThinkPad-T14-Gen-4.lan\n ([2001:9b1:925b:6407:f2e8:2f01:7b68:7422])\n by smtp.gmail.com with ESMTPSA id\n 2adb3069b0e04-5a4187e7bbdsm343768e87.66.2026.04.17.05.00.13\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 17 Apr 2026 05:00:13 -0700 (PDT)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:Cc\n\t:To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:\n\tResent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:\n\tList-Owner; bh=QseuZ6wdFd1/Yx2FT9xBKG7OoXBBQTRZtmxkXKj9MjY=; b=TG9tyj+8lGeP78\n\tzqlxMeT2mJKedgSsnF7v43y+6/XVcM2KKYkfCVvs4nQs1Rzkmhb3qq7YXVk2F6o+vS1zhgxxzfTfU\n\tOMItYQH2DsnW9rWVRutKZ0H/o4dbX49LEj7bVsQG6A+PAKiCx+SLkOLXal/qN+BCVpMrRvLwHGM1j\n\tSkhOUgxGwiVyqDSXbIP60Jsg9mKHfWaY5kVShrdE08uoinUPyrHv5InL9v6KosF7845ziwqPeF2yZ\n\t30vfRIrWgVIOuRf+oyDc8JojenFYC2+yku3g1a8IT+mtretgtDTICdcyNoQ1oYFGmd0Nkv77FOa70\n\tSy9psauCbzMPvs80+tQQ==;", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1776427215; x=1777032015;\n darn=lists.openwrt.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=bF3n1JfN/LGL7URTfvElTurETJQvBJ/mlJCeTzzG42w=;\n b=AwxL7w15VH3/cO6Sp0SbRTXgd5O7+kWS36Rpw3KyGjpk9Ipp77cstGetifZK/dHaHb\n C17W1ygkY0bDUgQnF89dwsgzs6ni/keeab136CaWdyWuhufaXJ9I2FJJA/P8IMqwzmiI\n zHBsrwPnMcZ1sVANv2y27f3lG3Y+sC5UvKsIpk39uHGLBzKIcoGOzob/xThdsLWmRhx8\n ubENefBs4l0o3Nwh1FuJxPiWAkdBv0HSC8+h4XDhyK1bKDPp/8kqMT7FMHwqpeoPi6UB\n GZ+/yGSoFZCzQPLpPetmj75PJTWPfe/bc7vDnM8d/IPmc49+rXhF46tnZORRcrIchS9x\n nwsw==" ], "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776427215; x=1777032015;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=bF3n1JfN/LGL7URTfvElTurETJQvBJ/mlJCeTzzG42w=;\n b=VRe5Whl5iytlgO9Y/aRd5fG1rk1nSr+AWDWxo79ef3jfcVOypp3yuIsEAZg/PV135D\n STBOvU/2TDpkDC2sxGLWnfTNjBumOqtbknXEDbzRhtcJoV2k+ZiUr6VtO0lJ4IG9RUp0\n 5ijGi3OEWZLDRlWNSiCOPxaGqaGUGhtJfBz4jQWrKazH5Ksma+3waOClOdkiIVUAEdT/\n sYCEE4cdesFTwF5MQavpjDUIhZWl4PaIJL+ZILZ8hhWjjXfQDYN6iL4YYxOBxaw3Gg04\n Yg39KkvvMduB3CKyA/jx//cfeI/4N89dL+clsM+YkH169W88di6sSLmqWb6xSPSzn6ef\n J3+Q==", "X-Gm-Message-State": "AOJu0YzLmTU29SxkW0bgmjSUEzJATV0Fu7iMt3zz6EQpbH2dnyJXJPby\n\tRNrCCmqFZI/g2cCSQtVPCV+25a9/Se63KYVUiXAYI8fvKM7MxPVYUPXC", "X-Gm-Gg": "AeBDievzKEszmUgY1QHdj59Io/RnV1PVQONmRK11M23SSIuwj2zha7c3z9VeEuVxO5g\n\tFF5c0aHpDnsg1+izjVEjxqp2vffUnc9/r3ECLK9dhMb9l7Up3Bt4c76o9bG5wX0mf1ZKaAhi7WV\n\tTlg6DrBnKHYpqN9VmLVL2Nc/Tjlbm/aQC1iPcI6osTnWXtM4Xu5IGcatoRM+e8ricd5MqTPQYdZ\n\tPb8hVDc8CHuCtG759NGoKPW6/syHX4ytVKwCRuU23TPgu80gsxCibDCJkIXGBNP520KEQlUNGht\n\thA0ZnGkTDlRrvZP61RUK3y2dUF1BBMBQhRUgK9gQ9McAW41OQhEw5dPvi+sZKGIcuDsSAfE7TPx\n\t7N17Pg2piVoSPJ+LpJFp1eBZLBPwpftxUVVemejsuxpeZ2dBKQdH89cQmEg/55wFdxgKBbvfBT4\n\tf8VOTLAzfanAwZQEVKKv4vQV7HPU1+LVPQJreNFEwl+3T0ocK3YOjQEcRCYqTXNEfaVDE+XSKle\n\t1o=", "X-Received": "by 2002:a05:6512:12c6:b0:5a2:ad98:3685 with SMTP id\n 2adb3069b0e04-5a4172e7b68mr778093e87.35.1776427214433;\n Fri, 17 Apr 2026 05:00:14 -0700 (PDT)", "From": "Erik Karlsson <erik.r.karlsson@gmail.com>", "To": "john@phrozen.org", "Cc": "openwrt-devel@lists.openwrt.org,\n\tErik Karlsson <erik.karlsson@iopsys.eu>", "Subject": "[PATCH mdnsd] dns: support additional section and SRV/TXT queries", "Date": "Fri, 17 Apr 2026 13:59:12 +0200", "Message-ID": "<20260417115912.3219321-1-erik.r.karlsson@gmail.com>", "X-Mailer": "git-send-email 2.53.0", "MIME-Version": "1.0", "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ", "X-CRM114-CacheID": "sfid-20260417_050017_177044_BEBE5A9E ", "X-CRM114-Status": "GOOD ( 19.75 )", "X-Spam-Score": "-2.1 (--)", "X-Spam-Report": "Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam. The original\n message has been attached to this so you can view it or label\n similar future email. If you have any questions, see\n the administrator of that system for details.\n Content preview: From: Erik Karlsson When responding to a PTR query, SRV and\n TXT records should be placed in the additional section and not the answer\n section. When responding to an A or AAAA query, addresses of mismatching\n type should b [...]\n Content analysis details: (-2.1 points, 5.0 required)\n pts rule name description\n ---- ----------------------\n --------------------------------------------------\n -0.0 SPF_PASS SPF: sender matches SPF record\n 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record\n -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from\n envelope-from domain\n 0.1 DKIM_SIGNED Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from\n author's\n domain\n -0.1 DKIM_VALID Message has at least one valid DKIM or DK\n signature\n -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1%\n [score: 0.0000]\n 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail\n provider\n [erik.r.karlsson(at)gmail.com]\n -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no\n trust\n [2a00:1450:4864:20:0:0:0:12f listed in]\n [list.dnswl.org]", "X-BeenThere": "openwrt-devel@lists.openwrt.org", "X-Mailman-Version": "2.1.34", "Precedence": "list", "List-Id": "OpenWrt Development List <openwrt-devel.lists.openwrt.org>", "List-Unsubscribe": "<https://lists.openwrt.org/mailman/options/openwrt-devel>,\n <mailto:openwrt-devel-request@lists.openwrt.org?subject=unsubscribe>", "List-Archive": "<http://lists.openwrt.org/pipermail/openwrt-devel/>", "List-Post": "<mailto:openwrt-devel@lists.openwrt.org>", "List-Help": "<mailto:openwrt-devel-request@lists.openwrt.org?subject=help>", "List-Subscribe": "<https://lists.openwrt.org/mailman/listinfo/openwrt-devel>,\n <mailto:openwrt-devel-request@lists.openwrt.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Sender": "\"openwrt-devel\" <openwrt-devel-bounces@lists.openwrt.org>", "Errors-To": "\n openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org" }, "content": "From: Erik Karlsson <erik.karlsson@iopsys.eu>\n\nWhen responding to a PTR query, SRV and TXT records should be placed\nin the additional section and not the answer section. When responding\nto an A or AAAA query, addresses of mismatching type should be placed\nin the additional section and not the answer section.\n\nRespond to SRV and TXT queries. Only respond to PTR queries without\ninstance specified (instance is not included in name of PTR records).\nPTR/SRV/TXT responses are always forced to yield predictable results.\nRate limiting is only kept for the legacy ANY query handling.\n\nFix a bug where the timeout was updated even if the response is forced\nand potential NULL pointer issues.\n\nSigned-off-by: Erik Karlsson <erik.karlsson@iopsys.eu>\n---\n dns.c | 88 ++++++++++++++++++++++++++++++++++++++++++-------------\n dns.h | 1 +\n service.c | 37 +++++++++++++++--------\n service.h | 2 +-\n 4 files changed, 93 insertions(+), 35 deletions(-)", "diff": "diff --git a/dns.c b/dns.c\nindex 6e7ec15..c66ea74 100644\n--- a/dns.c\n+++ b/dns.c\n@@ -150,13 +150,16 @@ bool dns_packet_question(const char *name, int type)\n \treturn true;\n }\n \n-void dns_packet_answer(const char *name, int type, const uint8_t *rdata, uint16_t rdlength, int ttl)\n+static bool dns_packet_record(const char *name, int type, const uint8_t *rdata, uint16_t rdlength, int ttl)\n {\n \tstruct dns_answer *a;\n \n \tpkt.h.flags |= cpu_to_be16(0x8400);\n \n \ta = dns_packet_record_add(sizeof(*a) + rdlength, name);\n+\tif (!a)\n+\t\treturn false;\n+\n \tmemset(a, 0, sizeof(*a));\n \ta->type = cpu_to_be16(type);\n \ta->class = cpu_to_be16(1);\n@@ -165,7 +168,19 @@ void dns_packet_answer(const char *name, int type, const uint8_t *rdata, uint16_\n \tmemcpy(a + 1, rdata, rdlength);\n \tDBG(1, \"A <- %s %s\\n\", dns_type_string(be16_to_cpu(a->type)), name);\n \n-\tpkt.h.answers += cpu_to_be16(1);\n+\treturn true;\n+}\n+\n+void dns_packet_answer(const char *name, int type, const uint8_t *rdata, uint16_t rdlength, int ttl)\n+{\n+\tif (dns_packet_record(name, type, rdata, rdlength, ttl))\n+\t\tpkt.h.answers += cpu_to_be16(1);\n+}\n+\n+void dns_packet_additional(const char *name, int type, const uint8_t *rdata, uint16_t rdlength, int ttl)\n+{\n+\tif (dns_packet_record(name, type, rdata, rdlength, ttl))\n+\t\tpkt.h.additional += cpu_to_be16(1);\n }\n \n static void dns_question_set_multicast(struct dns_question *q, bool val)\n@@ -184,6 +199,9 @@ void dns_packet_send(struct interface *iface, struct sockaddr *to, bool query, i\n \t};\n \tsize_t i;\n \n+\tif ((query && pkt.h.questions == 0) || (!query && pkt.h.answers == 0))\n+\t\treturn;\n+\n \tif (query) {\n \t\tif (multicast < 0)\n \t\t\tmulticast = iface->need_multicast;\n@@ -265,8 +283,8 @@ void dns_query(const char *name, uint16_t type)\n \t\tuloop_timeout_set(&timer, 100);\n }\n \n-void\n-dns_reply_a(struct interface *iface, struct sockaddr *to, int ttl, const char *hostname)\n+static void\n+dns_reply_a_qtype(struct interface *iface, struct sockaddr *to, int ttl, const char *hostname, uint16_t qtype)\n {\n \tstruct ifaddrs *ifap, *ifa;\n \tstruct sockaddr_in *sa;\n@@ -281,20 +299,45 @@ dns_reply_a(struct interface *iface, struct sockaddr *to, int ttl, const char *h\n \tfor (ifa = ifap; ifa; ifa = ifa->ifa_next) {\n \t\tif (strcmp(ifa->ifa_name, iface->name))\n \t\t\tcontinue;\n-\t\tif (ifa->ifa_addr->sa_family == AF_INET) {\n+\t\tif (ifa->ifa_addr->sa_family == AF_INET && (qtype == TYPE_ANY || qtype == TYPE_A)) {\n \t\t\tsa = (struct sockaddr_in *) ifa->ifa_addr;\n \t\t\tdns_packet_answer(hostname, TYPE_A, (uint8_t *) &sa->sin_addr, 4, ttl);\n \t\t}\n-\t\tif (ifa->ifa_addr->sa_family == AF_INET6) {\n+\t\tif (ifa->ifa_addr->sa_family == AF_INET6 && (qtype == TYPE_ANY || qtype == TYPE_AAAA)) {\n \t\t\tsa6 = (struct sockaddr_in6 *) ifa->ifa_addr;\n \t\t\tdns_packet_answer(hostname, TYPE_AAAA, (uint8_t *) &sa6->sin6_addr, 16, ttl);\n \t\t}\n \t}\n+\tif (qtype == TYPE_A) {\n+\t\tfor (ifa = ifap; ifa; ifa = ifa->ifa_next) {\n+\t\t\tif (strcmp(ifa->ifa_name, iface->name))\n+\t\t\t\tcontinue;\n+\t\t\tif (ifa->ifa_addr->sa_family == AF_INET6) {\n+\t\t\t\tsa6 = (struct sockaddr_in6 *) ifa->ifa_addr;\n+\t\t\t\tdns_packet_additional(hostname, TYPE_AAAA, (uint8_t *) &sa6->sin6_addr, 16, ttl);\n+\t\t\t}\n+\t\t}\n+\t} else if (qtype == TYPE_AAAA) {\n+\t\tfor (ifa = ifap; ifa; ifa = ifa->ifa_next) {\n+\t\t\tif (strcmp(ifa->ifa_name, iface->name))\n+\t\t\t\tcontinue;\n+\t\t\tif (ifa->ifa_addr->sa_family == AF_INET) {\n+\t\t\t\tsa = (struct sockaddr_in *) ifa->ifa_addr;\n+\t\t\t\tdns_packet_additional(hostname, TYPE_A, (uint8_t *) &sa->sin_addr, 4, ttl);\n+\t\t\t}\n+\t\t}\n+\t}\n \tfreeifaddrs(ifap);\n \n \tdns_packet_send(iface, to, 0, 0);\n }\n \n+void\n+dns_reply_a(struct interface *iface, struct sockaddr *to, int ttl, const char *hostname)\n+{\n+\tdns_reply_a_qtype(iface, to, ttl, hostname, TYPE_ANY);\n+}\n+\n void\n dns_reply_a_additional(struct interface *iface, struct sockaddr *to, int ttl)\n {\n@@ -602,7 +645,7 @@ parse_question(struct interface *iface, struct sockaddr *from, char *name, struc\n \t\tif (!strcasecmp(name, mdns_hostname_local)) {\n \t\t\tdns_reply_a(iface, to, announce_ttl, NULL);\n \t\t\tdns_reply_a_additional(iface, to, announce_ttl);\n-\t\t\tservice_reply(iface, to, NULL, NULL, announce_ttl, is_unicast);\n+\t\t\tservice_reply(iface, to, NULL, NULL, announce_ttl, is_unicast, q->type);\n \t\t}\n \t\tbreak;\n \n@@ -634,18 +677,21 @@ parse_question(struct interface *iface, struct sockaddr *from, char *name, struc\n \n \t\tif (!strcasecmp(name, C_DNS_SD)) {\n \t\t\tservice_announce_services(iface, to, announce_ttl);\n-\t\t} else {\n-\t\t\tif (name[0] == '_') {\n-\t\t\t\tservice_reply(iface, to, NULL, name, announce_ttl, is_unicast);\n-\t\t\t} else {\n-\t\t\t\t/* First dot separates instance name from the rest */\n-\t\t\t\tchar *dot = strchr(name, '.');\n-\n-\t\t\t\tif (dot) {\n-\t\t\t\t\t*dot = '\\0';\n-\t\t\t\t\tservice_reply(iface, to, name, dot + 1, announce_ttl, is_unicast);\n-\t\t\t\t\t*dot = '.';\n-\t\t\t\t}\n+\t\t} else if (name[0] == '_') {\n+\t\t\tservice_reply(iface, to, NULL, name, announce_ttl, 1, q->type);\n+\t\t}\n+\t\tbreak;\n+\n+\tcase TYPE_SRV:\n+\tcase TYPE_TXT:\n+\t\tif (name[0] != '_') {\n+\t\t\t/* First dot separates instance name from the rest */\n+\t\t\tchar *dot = strchr(name, '.');\n+\n+\t\t\tif (dot) {\n+\t\t\t\t*dot = '\\0';\n+\t\t\t\tservice_reply(iface, to, name, dot + 1, announce_ttl, 1, q->type);\n+\t\t\t\t*dot = '.';\n \t\t\t}\n \t\t}\n \t\tbreak;\n@@ -656,13 +702,13 @@ parse_question(struct interface *iface, struct sockaddr *from, char *name, struc\n \t\tif (host)\n \t\t\t*host = '\\0';\n \t\tif (!strcasecmp(umdns_host_label, name)) {\n-\t\t\tdns_reply_a(iface, to, announce_ttl, NULL);\n+\t\t\tdns_reply_a_qtype(iface, to, announce_ttl, NULL, q->type);\n \t\t} else {\n \t\t\tif (host)\n \t\t\t\t*host = '.';\n \t\t\tvlist_for_each_element(&hostnames, h, node)\n \t\t\t\tif (!strcasecmp(h->hostname, name))\n-\t\t\t\t\tdns_reply_a(iface, to, announce_ttl, h->hostname);\n+\t\t\t\t\tdns_reply_a_qtype(iface, to, announce_ttl, h->hostname, q->type);\n \t\t}\n \t\tbreak;\n \t};\ndiff --git a/dns.h b/dns.h\nindex ed0907d..3630222 100644\n--- a/dns.h\n+++ b/dns.h\n@@ -83,6 +83,7 @@ extern int cfg_no_subnet;\n void dns_packet_init(void);\n bool dns_packet_question(const char *name, int type);\n void dns_packet_answer(const char *name, int type, const uint8_t *rdata, uint16_t rdlength, int ttl);\n+void dns_packet_additional(const char *name, int type, const uint8_t *rdata, uint16_t rdlength, int ttl);\n void dns_packet_send(struct interface *iface, struct sockaddr *to, bool query, int multicast);\n \n void dns_query(const char *name, uint16_t type);\ndiff --git a/service.c b/service.c\nindex 441ec2e..01c6f90 100644\n--- a/service.c\n+++ b/service.c\n@@ -89,7 +89,7 @@ service_add_ptr(const char *name, const char *host, int ttl)\n }\n \n static void\n-service_add_srv(const char *name, struct service *s, int ttl)\n+service_add_srv(const char *name, struct service *s, int ttl, int answer)\n {\n \tstruct dns_srv_data *sd = (struct dns_srv_data *) mdns_buf;\n \tint len = sizeof(*sd);\n@@ -99,7 +99,10 @@ service_add_srv(const char *name, struct service *s, int ttl)\n \t\treturn;\n \n \tsd->port = cpu_to_be16(s->port);\n-\tdns_packet_answer(name, TYPE_SRV, mdns_buf, len, ttl);\n+\tif (answer)\n+\t\tdns_packet_answer(name, TYPE_SRV, mdns_buf, len, ttl);\n+\telse\n+\t\tdns_packet_additional(name, TYPE_SRV, mdns_buf, len, ttl);\n }\n \n #define TOUT_LOOKUP\t60\n@@ -118,29 +121,37 @@ service_timeout(struct service *s)\n }\n \n static void\n-service_reply_single(struct interface *iface, struct sockaddr *to, struct service *s, int ttl, int force)\n+service_reply_single(struct interface *iface, struct sockaddr *to, struct service *s, int ttl, int force, uint16_t qtype)\n {\n \tconst char *host = service_instance_name(s);\n \tchar *service = strstr(host, \"._\");\n-\ttime_t t = service_timeout(s);\n+\ttime_t t = force ? 0 : service_timeout(s);\n \n-\tif (!force && (!s->active || !service || !t))\n+\tif ((!force && (!s->active || !t)) || !service)\n \t\treturn;\n \n \tservice++;\n \n-\ts->t = t;\n+\tif (t)\n+\t\ts->t = t;\n \n \tdns_packet_init();\n-\tservice_add_ptr(service, service_instance_name(s), ttl);\n-\tservice_add_srv(host, s, ttl);\n-\tif (s->txt && s->txt_len)\n+\tif (qtype == TYPE_ANY || qtype == TYPE_PTR)\n+\t\tservice_add_ptr(service, host, ttl);\n+\tif (qtype == TYPE_ANY || qtype == TYPE_SRV)\n+\t\tservice_add_srv(host, s, ttl, 1);\n+\tif (s->txt && s->txt_len && (qtype == TYPE_ANY || qtype == TYPE_TXT))\n \t\tdns_packet_answer(host, TYPE_TXT, (uint8_t *) s->txt, s->txt_len, ttl);\n+\tif (qtype == TYPE_PTR) {\n+\t\tservice_add_srv(host, s, ttl, 0);\n+\t\tif (s->txt && s->txt_len)\n+\t\t\tdns_packet_additional(host, TYPE_TXT, (uint8_t *) s->txt, s->txt_len, ttl);\n+\t}\n \tdns_packet_send(iface, to, 0, 0);\n }\n \n void\n-service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl, int force)\n+service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl, int force, uint16_t qtype)\n {\n \tstruct service *s;\n \n@@ -149,7 +160,7 @@ service_reply(struct interface *iface, struct sockaddr *to, const char *instance\n \t\t\tcontinue;\n \t\tif (service_domain && strcmp(s->service, service_domain))\n \t\t\tcontinue;\n-\t\tservice_reply_single(iface, to, s, ttl, force);\n+\t\tservice_reply_single(iface, to, s, ttl, force, qtype);\n \t}\n }\n \n@@ -183,7 +194,7 @@ service_update(struct vlist_tree *tree, struct vlist_node *node_new,\n \t\tif (service_init_announce)\n \t\t\tvlist_for_each_element(&interfaces, iface, node) {\n \t\t\t\ts->t = 0;\n-\t\t\t\tservice_reply_single(iface, NULL, s, announce_ttl, 1);\n+\t\t\t\tservice_reply_single(iface, NULL, s, announce_ttl, 1, TYPE_ANY);\n \t\t\t}\n \t\treturn;\n \t}\n@@ -191,7 +202,7 @@ service_update(struct vlist_tree *tree, struct vlist_node *node_new,\n \ts = container_of(node_old, struct service, node);\n \tif (!node_new && service_init_announce)\n \t\tvlist_for_each_element(&interfaces, iface, node)\n-\t\t\tservice_reply_single(iface, NULL, s, 0, 1);\n+\t\t\tservice_reply_single(iface, NULL, s, 0, 1, TYPE_ANY);\n \tfree(s);\n }\n \ndiff --git a/service.h b/service.h\nindex 7149672..2fdc954 100644\n--- a/service.h\n+++ b/service.h\n@@ -42,7 +42,7 @@ extern struct vlist_tree announced_services;\n \n extern void service_init(int announce);\n extern void service_cleanup(void);\n-extern void service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl, int force);\n+extern void service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl, int force, uint16_t qtype);\n extern void service_announce_services(struct interface *iface, struct sockaddr *to, int ttl);\n extern void service_update(struct vlist_tree *tree, struct vlist_node *node_new, struct vlist_node *node_old);\n \n", "prefixes": [ "mdnsd" ] }