get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2219759/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2219759,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2219759/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/hostap/patch/20260402095356.1401176-3-allen.ye@mediatek.com/",
    "project": {
        "id": 22,
        "url": "http://patchwork.ozlabs.org/api/1.1/projects/22/?format=api",
        "name": "HostAP Development",
        "link_name": "hostap",
        "list_id": "hostap.lists.infradead.org",
        "list_email": "hostap@lists.infradead.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260402095356.1401176-3-allen.ye@mediatek.com>",
    "date": "2026-04-02T09:53:51",
    "name": "[v11,2/7] hostapd: afcd: Add AFC daemon support",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "2b6d224e1977f3a50d03f7fafc58db7e9b3eb097",
    "submitter": {
        "id": 86975,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/86975/?format=api",
        "name": "Allen Ye",
        "email": "Allen.Ye@mediatek.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/hostap/patch/20260402095356.1401176-3-allen.ye@mediatek.com/mbox/",
    "series": [
        {
            "id": 498460,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/498460/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/hostap/list/?series=498460",
            "date": "2026-04-02T09:53:56",
            "name": "Introduce Automated Frequency Coordination (AFC) support",
            "version": 11,
            "mbox": "http://patchwork.ozlabs.org/series/498460/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2219759/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2219759/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.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=JExwpdew;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=mediatek.com header.i=@mediatek.com header.a=rsa-sha256\n header.s=dk header.b=QPTbW0Em;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.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 4fnpHN2mmxz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 04 Apr 2026 19:12:48 +1100 (AEDT)",
            "from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1w8w75-00000003Gy5-0jGv;\n\tSat, 04 Apr 2026 08:12:15 +0000",
            "from mailgw02.mediatek.com ([216.200.240.185])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1w8Ekk-0000000HJwd-3agA\n\tfor hostap@lists.infradead.org;\n\tThu, 02 Apr 2026 09:54:20 +0000",
            "from mtkmbs14n2.mediatek.inc [(172.21.101.76)] by\n mailgw02.mediatek.com\n\t(envelope-from <allen.ye@mediatek.com>)\n\t(musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384\n 256/256)\n\twith ESMTP id 1383811367; Thu, 02 Apr 2026 02:54:13 -0700",
            "from mtkmbs13n2.mediatek.inc (172.21.101.108) by\n mtkmbs13n2.mediatek.inc (172.21.101.108) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.2.2562.29; Thu, 2 Apr 2026 17:54:11 +0800",
            "from mtksitap99.mediatek.inc (10.233.130.16) by\n mtkmbs13n2.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id\n 15.2.2562.29 via Frontend Transport; Thu, 2 Apr 2026 17:54:11 +0800"
        ],
        "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:References:In-Reply-To:\n\tMessage-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=SDh9ljjdvzFyamYYFVzikOSk3VemEG1+YU0OMkNhk5o=; b=JExwpdewzuKY7v\n\toKe0T5IXGMG9n/5ucmyj4VKbzMztQhYmgcaUZyMcFzfhKi2FSpxI22Bls3HnjawyXskcR3YmLckHn\n\t3j8OsmSixucS6aSkSlfvs0kDqDv7BPauManHi3Ct5kxvSPJIbB+Bu90ilwR31Daq5JBHAEkyaXdxs\n\tcifqJ2o0ht+2zk7szQZzmdL62kT1aBQBR7aHIaSnw3uLKLh1z052RtUe42jgoDgxkN1dgFufpLPQj\n\tAyNBLOzYwMu+j4eCrhJpD4l4lRGI3cxW9FIUIsTarnQP3nreE2hSUNJIFuxVFavp/52SKpiJEksA8\n\tKREw4bg+C8T1CpIZq5QQ==;",
            "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n d=mediatek.com; s=dk;\n\th=Content-Type:Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;\n bh=nOx9Fl9m/VQfnW6p9mDloobvrYJDsgb1Bf14ZllzudA=;\n\tb=QPTbW0Em5kwyTVEUKW9U0nsUPEBxV7q+YYqtYaN2N66GrKWRrZa1oO0kEn6C53562o3L5zDaEY3cvm66yJP6G/JcF05K2nQSzLh2QkDMSl1PqBVGFr5xhiQu0uc/1OH9WPpTZEWJqheNZRxwVvASJsAsSOvsO9S+viB+V0n86wg=;"
        ],
        "X-UUID": [
            "e790289c2e7911f1a6de359d7043e138-20260402",
            "e790289c2e7911f1a6de359d7043e138-20260402"
        ],
        "X-CID-P-RULE": "Release_Ham",
        "X-CID-O-INFO": "VERSION:1.3.12,REQID:5a4fb9db-e880-4899-8209-b09893d99a04,IP:0,U\n\tRL:0,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION\n\t:release,TS:-5",
        "X-CID-META": "VersionHash:e7bac3a,CLOUDID:303785a7-e101-400a-acb5-0dbb5a913469,B\n\tulkID:nil,BulkQuantity:0,Recheck:0,SF:81|82|102|836|865|888|898,TC:-5,Cont\n\tent:0|15|50,EDM:-3,IP:nil,URL:1,File:130,RT:0,Bulk:nil,QS:nil,BEC:-1,COL:0\n\t,OSI:0,OSA:0,AV:0,LES:1,SPR:NO,DKR:0,DKP:0,BRR:0,BRE:0,ARC:0",
        "X-CID-BVR": "2,SSN|SDN",
        "X-CID-BAS": "2,SSN|SDN,0,_",
        "X-CID-FACTOR": "TF_CID_SPAM_SNR,TF_CID_SPAM_ULS",
        "X-CID-RHF": "D41D8CD98F00B204E9800998ECF8427E",
        "From": "Allen Ye <allen.ye@mediatek.com>",
        "To": "Jouni Malinen <j@w1.fi>",
        "CC": "<hostap@lists.infradead.org>, Felix Fietkau <nbd@nbd.name>, Evelyn Tsai\n\t<evelyn.tsai@mediatek.com>, \"Mark-MC . Lee\" <mark-mc.lee@mediatek.com>, Tarun\n Radhakrishnan <tarun.r@tataelxsi.co.in>, Lorenzo Bianconi\n\t<lorenzo@kernel.org>, Allen Ye <allen.ye@mediatek.com>, Krishna Chaitanya\n\t<chaitanya.mgit@gmail.com>, Sriya Nair <sriya.n@tataelxsi.co.in>",
        "Subject": "[PATCH v11 2/7] hostapd: afcd: Add AFC daemon support",
        "Date": "Thu, 2 Apr 2026 17:53:51 +0800",
        "Message-ID": "<20260402095356.1401176-3-allen.ye@mediatek.com>",
        "X-Mailer": "git-send-email 2.45.2",
        "In-Reply-To": "<20260402095356.1401176-1-allen.ye@mediatek.com>",
        "References": "<20260402095356.1401176-1-allen.ye@mediatek.com>",
        "MIME-Version": "1.0",
        "X-MTK": "N",
        "X-CRM114-Version": "20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ",
        "X-CRM114-CacheID": "sfid-20260402_025418_926488_54F7ADC1 ",
        "X-CRM114-Status": "GOOD (  22.31  )",
        "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: Lorenzo Bianconi <lorenzo@kernel.org> Introduce\n Automated\n    Frequency Coordination Daemon (AFCD) support for UNII-5 and UNII-7 6GHz\n bands.\n    AFCD will be used by hostapd AFC client in order to forward the AFC\n request\n    to the AFC coordinator an [...]\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_PASS          SPF: HELO matches SPF record\n  0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from\n                             envelope-from domain\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 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n                              Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                             [216.200.240.185 listed in\n sa-accredit.habeas.com]\n  0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The\n                             query to Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                        [216.200.240.185 listed in\n sa-trusted.bondedsender.org]\n  0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to\n                              Validity was blocked.  See\n                             https://knowledge.validity.com/hc/en-us/articles/20961730681243\n                              for more information.\n                           [216.200.240.185 listed in\n bl.score.senderscore.com]\n  0.0 UNPARSEABLE_RELAY      Informational: message has unparseable relay\n lines",
        "X-Mailman-Approved-At": "Sat, 04 Apr 2026 01:12:14 -0700",
        "X-BeenThere": "hostap@lists.infradead.org",
        "X-Mailman-Version": "2.1.34",
        "Precedence": "list",
        "List-Id": "<hostap.lists.infradead.org>",
        "List-Unsubscribe": "<http://lists.infradead.org/mailman/options/hostap>,\n <mailto:hostap-request@lists.infradead.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.infradead.org/pipermail/hostap/>",
        "List-Post": "<mailto:hostap@lists.infradead.org>",
        "List-Help": "<mailto:hostap-request@lists.infradead.org?subject=help>",
        "List-Subscribe": "<http://lists.infradead.org/mailman/listinfo/hostap>,\n <mailto:hostap-request@lists.infradead.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Sender": "\"Hostap\" <hostap-bounces@lists.infradead.org>",
        "Errors-To": "hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org"
    },
    "content": "From: Lorenzo Bianconi <lorenzo@kernel.org>\n\nIntroduce Automated Frequency Coordination Daemon (AFCD) support\nfor UNII-5 and UNII-7 6GHz bands.\nAFCD will be used by hostapd AFC client in order to forward the AFC\nrequest to the AFC coordinator and decouple AFC connection management\nfrom hostapd.\nAFC is required for Standard Power Devices (SPDs) to determine a list\nof channels and EIRP/PSD values that are available in the 6GHz spectrum.\nAFCD is tested with AFC DUT Test Harness [0].\nAdd afc-reply.txt as reference for replies from the AFC coordinator.\n\n[0] https://github.com/Wi-FiTestSuite/AFC-DUT/tree/main\n\nTested-by: Felix Fietkau <nbd@nbd.name>\nTested-by: Allen Ye <allen.ye@mediatek.com>\nTested-by: Krishna Chaitanya <chaitanya.mgit@gmail.com>\nSigned-off-by: Lorenzo Bianconi <lorenzo@kernel.org>\nSigned-off-by: Sriya Nair <sriya.n@tataelxsi.co.in>\nSigned-off-by: Allen Ye <allen.ye@mediatek.com>\n---\n afc/.gitignore    |   1 +\n afc/Makefile      |  31 ++++\n afc/afc-reply.txt | 219 +++++++++++++++++++++++++\n afc/afcd.c        | 402 ++++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 653 insertions(+)\n create mode 100644 afc/.gitignore\n create mode 100644 afc/Makefile\n create mode 100644 afc/afc-reply.txt\n create mode 100644 afc/afcd.c",
    "diff": "diff --git a/afc/.gitignore b/afc/.gitignore\nnew file mode 100644\nindex 000000000..8d8cca905\n--- /dev/null\n+++ b/afc/.gitignore\n@@ -0,0 +1 @@\n+afcd\ndiff --git a/afc/Makefile b/afc/Makefile\nnew file mode 100644\nindex 000000000..a83bd01db\n--- /dev/null\n+++ b/afc/Makefile\n@@ -0,0 +1,31 @@\n+ALL=afcd\n+\n+include ../src/build.rules\n+\n+CFLAGS += -I../src/utils\n+CFLAGS += -I../src\n+\n+OBJS=afcd.o\n+OBJS += ../src/utils/common.o\n+OBJS += ../src/utils/wpa_debug.o\n+OBJS += ../src/utils/wpabuf.o\n+\n+ifndef CONFIG_OS\n+ifdef CONFIG_NATIVE_WINDOWS\n+CONFIG_OS=win32\n+else\n+CONFIG_OS=unix\n+endif\n+endif\n+OBJS += ../src/utils/os_$(CONFIG_OS).o\n+\n+LIBS += -lcurl\n+\n+_OBJS_VAR := OBJS\n+include ../src/objs.mk\n+afcd: $(OBJS)\n+\t$(Q)$(LDO) $(LDFLAGS) -o afcd $(OBJS) $(LIBS)\n+\t@$(E) \"  LD \" $@\n+\n+clean: common-clean\n+\trm -f core *~\ndiff --git a/afc/afc-reply.txt b/afc/afc-reply.txt\nnew file mode 100644\nindex 000000000..aaa4f8956\n--- /dev/null\n+++ b/afc/afc-reply.txt\n@@ -0,0 +1,219 @@\n+HTTP/1.1 200 OK\n+Content-Type: application/json\n+Content-Length: 4843\n+\n+{\n+   \"availableSpectrumInquiryResponses\":[\n+      {\n+         \"availabilityExpireTime\":\"2023-02-23T12:53:18Z\",\n+         \"availableChannelInfo\":[\n+            {\n+               \"channelCfi\":[\n+                  1,\n+                  5,\n+                  9,\n+                  13,\n+                  17,\n+                  21,\n+                  25,\n+                  29,\n+                  33,\n+                  37,\n+                  41,\n+                  45,\n+                  49,\n+                  53,\n+                  57,\n+                  61,\n+                  65,\n+                  69,\n+                  73,\n+                  77,\n+                  81,\n+                  85,\n+                  89,\n+                  93,\n+                  117,\n+                  121,\n+                  125,\n+                  129,\n+                  133,\n+                  137,\n+                  141,\n+                  145,\n+                  149,\n+                  153,\n+                  157,\n+                  161,\n+                  165,\n+                  169,\n+                  173,\n+                  177,\n+                  181\n+               ],\n+               \"globalOperatingClass\":131,\n+               \"maxEirp\":[\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5\n+               ]\n+            },\n+            {\n+               \"channelCfi\":[\n+                  3,\n+                  11,\n+                  19,\n+                  27,\n+                  35,\n+                  43,\n+                  51,\n+                  59,\n+                  67,\n+                  75,\n+                  83,\n+                  91,\n+                  123,\n+                  131,\n+                  139,\n+                  147,\n+                  155,\n+                  163,\n+                  171,\n+                  179\n+               ],\n+               \"globalOperatingClass\":132,\n+               \"maxEirp\":[\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5\n+               ]\n+            },\n+            {\n+               \"channelCfi\":[\n+                  7,\n+                  23,\n+                  39,\n+                  55,\n+                  71,\n+                  87,\n+                  135,\n+                  151,\n+                  167\n+               ],\n+               \"globalOperatingClass\":133,\n+               \"maxEirp\":[\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5,\n+                  5\n+               ]\n+            },\n+            {\n+               \"channelCfi\":[\n+                  15,\n+                  47,\n+                  79,\n+                  143\n+               ],\n+               \"globalOperatingClass\":134,\n+               \"maxEirp\":[\n+                  5,\n+                  5,\n+                  5,\n+                  5\n+               ]\n+            },\n+            {\n+               \"channelCfi\":[\n+               ],\n+               \"globalOperatingClass\":135,\n+               \"maxEirp\":[\n+               ]\n+            }\n+         ],\n+         \"availableFrequencyInfo\":[\n+            {\n+               \"frequencyRange\":{\n+                  \"highFrequency\":6425,\n+                  \"lowFrequency\":5925\n+               },\n+               \"maxPSD\":3.98970004336019\n+            },\n+            {\n+               \"frequencyRange\":{\n+                  \"highFrequency\":6865,\n+                  \"lowFrequency\":6525\n+               },\n+               \"maxPSD\":3.98970004336019\n+            }\n+         ],\n+         \"requestId\":\"11235813\",\n+         \"response\":{\n+            \"responseCode\":0,\n+            \"shortDescription\":\"Success\"\n+         },\n+         \"rulesetId\":\"US_47_CFR_PART_15_SUBPART_E\"\n+      }\n+   ],\n+   \"version\":\"1.1\"\n+}\ndiff --git a/afc/afcd.c b/afc/afcd.c\nnew file mode 100644\nindex 000000000..09be2313f\n--- /dev/null\n+++ b/afc/afcd.c\n@@ -0,0 +1,402 @@\n+/*\n+ * Automated Frequency Coordination Daemon\n+ * Copyright (c) 2024, Lorenzo Bianconi <lorenzo@kernel.org>\n+ *\n+ * This software may be distributed under the terms of the BSD license.\n+ * See README for more details.\n+ */\n+\n+#include \"includes.h\"\n+#include <curl/curl.h>\n+#include <sys/un.h>\n+#include <sys/stat.h>\n+\n+#include \"utils/common.h\"\n+\n+#define CURL_TIMEOUT\t60\n+#define AFCD_SOCK\t\"afcd.sock\"\n+\n+struct curl_ctx {\n+\tchar *buf;\n+\tsize_t buf_len;\n+};\n+\n+static volatile bool exiting;\n+\n+static char *path = \"/var/run\";\n+static char *bearer_token;\n+static char *url;\n+static long port = 443;\n+\n+enum afcd_tls_mode {\n+\tAFCD_TLS12 = 0,\n+\tAFCD_TLS12_MTLS,\n+\tAFCD_TLS13,\n+\tAFCD_TLS13_MTLS,\n+};\n+static enum afcd_tls_mode tls_mode = AFCD_TLS12;\n+static bool use_mtls;\n+static char *client_cert;\t/* PEM or engine reference */\n+static char *client_key;\t/* optional separate key */\n+static char *client_key_pass;\t/* optional passphrase */\n+static char *cafile;\t\t/* optional CA bundle override */\n+\n+\n+static size_t afcd_curl_cb_write(void *ptr, size_t size, size_t nmemb,\n+\t\t\t\t void *userdata)\n+{\n+\tstruct curl_ctx *ctx = userdata;\n+\tchar *buf;\n+\n+\tbuf = os_realloc(ctx->buf, ctx->buf_len + size * nmemb + 1);\n+\tif (!buf)\n+\t\treturn 0;\n+\n+\tctx->buf = buf;\n+\tos_memcpy(buf + ctx->buf_len, ptr, size * nmemb);\n+\tbuf[ctx->buf_len + size * nmemb] = '\\0';\n+\tctx->buf_len += size * nmemb;\n+\n+\treturn size * nmemb;\n+}\n+\n+\n+static int afcd_send_request(struct curl_ctx *ctx, unsigned char *request)\n+{\n+\tstruct curl_slist *headers = NULL, *tmp;\n+\tint ret = CURLE_FAILED_INIT;\n+\tCURL *curl;\n+\n+\twpa_printf(MSG_DEBUG, \"Sending AFC request to %s\", url);\n+\n+\tcurl = curl_easy_init();\n+\tif (!curl)\n+\t\treturn -EINVAL;\n+\n+\theaders  = curl_slist_append(headers, \"Accept: application/json\");\n+\tif (!headers)\n+\t\tgoto out_easy_cleanup;\n+\n+\ttmp = curl_slist_append(headers, \"Content-Type: application/json\");\n+\tif (!tmp)\n+\t\tgoto out_slist_free_all;\n+\theaders = tmp;\n+\n+\ttmp = curl_slist_append(headers, \"charset: utf-8\");\n+\tif (!tmp)\n+\t\tgoto out_slist_free_all;\n+\theaders = tmp;\n+\n+\tcurl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n+\tcurl_easy_setopt(curl, CURLOPT_URL, url);\n+\tcurl_easy_setopt(curl, CURLOPT_PORT, port);\n+\tcurl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);\n+\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,\n+\t\t\t afcd_curl_cb_write);\n+\tcurl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);\n+\tcurl_easy_setopt(curl, CURLOPT_USERAGENT, \"libcrp/0.1\");\n+\tcurl_easy_setopt(curl, CURLOPT_TIMEOUT, (long) CURL_TIMEOUT);\n+\n+\tswitch (tls_mode) {\n+\tcase AFCD_TLS12:\n+\tcase AFCD_TLS12_MTLS:\n+\t\tcurl_easy_setopt(curl, CURLOPT_SSLVERSION,\n+\t\t\t\t (long) CURL_SSLVERSION_TLSv1_2);\n+\t\tbreak;\n+\tcase AFCD_TLS13:\n+\tcase AFCD_TLS13_MTLS:\n+\t\tcurl_easy_setopt(curl, CURLOPT_SSLVERSION,\n+\t\t\t\t (long) CURL_SSLVERSION_TLSv1_3);\n+\t\tbreak;\n+\tdefault:\n+\t\twpa_printf(MSG_ERROR, \"Unknown TLS selection %d\", tls_mode);\n+\t\tgoto out_slist_free_all;\n+\t}\n+\n+\tif (use_mtls) {\n+\t\tcurl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert);\n+\t\tif (client_key)\n+\t\t\tcurl_easy_setopt(curl, CURLOPT_SSLKEY, client_key);\n+\t\tif (client_key_pass)\n+\t\t\tcurl_easy_setopt(curl, CURLOPT_KEYPASSWD,\n+\t\t\t\t\t client_key_pass);\n+\t}\n+\n+\tif (bearer_token) {\n+\t\tcurl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, bearer_token);\n+\t\tcurl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);\n+\t}\n+\n+\tif (cafile)\n+\t\tcurl_easy_setopt(curl, CURLOPT_CAINFO, cafile);\n+\n+\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);\n+\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);\n+\tcurl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);\n+\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);\n+\n+\tret = curl_easy_perform(curl);\n+\tif (ret != CURLE_OK)\n+\t\twpa_printf(MSG_ERROR, \"curl_easy_perform failed: %s\",\n+\t\t\t   curl_easy_strerror(ret));\n+\n+out_slist_free_all:\n+\tcurl_slist_free_all(headers);\n+out_easy_cleanup:\n+\tcurl_easy_cleanup(curl);\n+\n+\treturn ret == CURLE_OK ? 0 : -EINVAL;\n+}\n+\n+\n+static void handle_term(int sig)\n+{\n+\twpa_printf(MSG_ERROR, \"Received signal %d\", sig);\n+\texiting = true;\n+}\n+\n+\n+static void usage(void)\n+{\n+\twpa_printf(MSG_ERROR,\n+\t\t   \"%s:\\n\"\n+\t\t   \"afcd -u<url> [-p<port>] [-t<token>] \"\n+\t\t   \"[-S<12|13>] [-M] [-c<client-cert.pem>] \"\n+\t\t   \"[-k<client-key.pem>] [-w<key-pass>] [-A<cafile>] \"\n+\t\t   \"[-D<unix-sock dir>] [-P<PID file>] [-dB]\",\n+\t\t   __func__);\n+}\n+\n+\n+#define BUFSIZE\t\t8192\n+static int afcd_server_run(void)\n+{\n+\tsize_t len = os_strlen(path) + 1 + os_strlen(AFCD_SOCK);\n+\tstruct sockaddr_un addr = {\n+\t\t.sun_family = AF_UNIX,\n+#ifdef __FreeBSD__\n+\t\t.sun_len = sizeof(addr),\n+#endif /* __FreeBSD__ */\n+\t};\n+\tint sockfd, ret = 0;\n+\tchar *fname = NULL;\n+\tunsigned char *buf;\n+\tfd_set read_set;\n+\n+\tif (len >= sizeof(addr.sun_path))\n+\t\treturn -EINVAL;\n+\n+\tif (mkdir(path, S_IRWXU | S_IRWXG) < 0 && errno != EEXIST)\n+\t\treturn -EINVAL;\n+\n+\tbuf = os_malloc(BUFSIZE);\n+\tif (!buf)\n+\t\treturn -ENOMEM;\n+\n+\tfname = os_malloc(len + 1);\n+\tif (!fname) {\n+\t\tret = -ENOMEM;\n+\t\tgoto free_buf;\n+\t}\n+\n+\tos_snprintf(fname, len + 1, \"%s/%s\", path, AFCD_SOCK);\n+\tos_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));\n+\n+\tsockfd = socket(AF_UNIX, SOCK_STREAM, 0);\n+\tif (sockfd < 0) {\n+\t\twpa_printf(MSG_ERROR, \"Failed creating socket\");\n+\t\tret = -errno;\n+\t\tgoto unlink;\n+\t}\n+\n+\tif (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"Failed to bind socket\");\n+\t\tret = -errno;\n+\t\tgoto close;\n+\t}\n+\n+\tif (listen(sockfd, 10) < 0) {\n+\t\twpa_printf(MSG_ERROR, \"Failed to listen on socket\");\n+\t\tret = -errno;\n+\t\tgoto close;\n+\t}\n+\n+\tcurl_global_init(CURL_GLOBAL_ALL);\n+\tFD_ZERO(&read_set);\n+\twhile (!exiting) {\n+\t\tsocklen_t addr_len = sizeof(addr);\n+\t\tstruct sockaddr_in6 c_addr;\n+\t\tstruct timeval timeout = {\n+\t\t\t.tv_sec = 1,\n+\t\t};\n+\t\tstruct curl_ctx ctx = {};\n+\t\tint fd;\n+\n+\t\tFD_SET(sockfd, &read_set);\n+\t\tif (select(sockfd + 1, &read_set, NULL, NULL, &timeout) < 0) {\n+\t\t\tif (errno != EINTR) {\n+\t\t\t\twpa_printf(MSG_ERROR,\n+\t\t\t\t\t   \"Select failed on socket\");\n+\t\t\t\tret = -errno;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!FD_ISSET(sockfd, &read_set))\n+\t\t\tcontinue;\n+\n+\t\tfd = accept(sockfd, (struct sockaddr *)&c_addr,\n+\t\t\t    &addr_len);\n+\t\tif (fd < 0) {\n+\t\t\tif (errno != EINTR) {\n+\t\t\t\twpa_printf(MSG_ERROR,\n+\t\t\t\t\t   \"Failed accepting connections\");\n+\t\t\t\tret = -errno;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tos_memset(buf, 0, BUFSIZE);\n+\t\tif (recv(fd, buf, BUFSIZE - 1, 0) <= 0) {\n+\t\t\tclose(fd);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tbuf[BUFSIZE - 1] = '\\0';\n+\n+\t\twpa_printf(MSG_DEBUG, \"Received request: %s\", buf);\n+\t\tif (!afcd_send_request(&ctx, buf)) {\n+\t\t\twpa_printf(MSG_DEBUG, \"Received reply: %s\", ctx.buf);\n+\t\t\tsend(fd, ctx.buf, ctx.buf_len, MSG_NOSIGNAL);\n+\t\t\tfree(ctx.buf);\n+\t\t}\n+\t\tclose(fd);\n+\t}\n+\tcurl_global_cleanup();\n+close:\n+\tclose(sockfd);\n+unlink:\n+\tunlink(fname);\n+\tos_free(fname);\n+free_buf:\n+\tos_free(buf);\n+\n+\treturn ret;\n+}\n+\n+\n+int main(int argc, char **argv)\n+{\n+\tbool daemonize = false;\n+\tchar *pid_file = NULL;\n+\tint ret = -EINVAL;\n+\n+\tif (os_program_init())\n+\t\treturn -1;\n+\n+\tfor (;;) {\n+\t\tint c = getopt(argc, argv, \"u:p:t:S:Mc:k:w:A:D:P:Bd\");\n+\n+\t\tif (c < 0)\n+\t\t\tbreak;\n+\n+\t\tswitch (c) {\n+\t\tcase 'h':\n+\t\t\tusage();\n+\t\t\tret = 0;\n+\t\t\tgoto out;\n+\t\tcase 'B':\n+\t\t\tdaemonize = true;\n+\t\t\tbreak;\n+\t\tcase 'D':\n+\t\t\tpath = optarg;\n+\t\t\tbreak;\n+\t\tcase 'P':\n+\t\t\tos_free(pid_file);\n+\t\t\tpid_file = os_rel2abs_path(optarg);\n+\t\t\tbreak;\n+\t\tcase 'u':\n+\t\t\turl = optarg;\n+\t\t\tbreak;\n+\t\tcase 'p':\n+\t\t\tport = atoi(optarg);\n+\t\t\tbreak;\n+\t\tcase 'd':\n+\t\t\tif (wpa_debug_level > 0)\n+\t\t\t\twpa_debug_level--;\n+\t\t\tbreak;\n+\t\tcase 't':\n+\t\t\tbearer_token = optarg;\n+\t\t\tbreak;\n+\t\tcase 'S':\n+\t\t\tif (!strcmp(optarg, \"12\"))\n+\t\t\t\ttls_mode = AFCD_TLS12;\n+\t\t\telse if (!strcmp(optarg, \"13\")) {\n+#ifndef CURL_SSLVERSION_TLSv1_3\n+\t\t\t\twpa_printf(MSG_ERROR,\n+\t\t\t\t\t   \"libcurl/SSL backend lacks TLSv1.3 support\");\n+\t\t\t\tgoto out;\n+#endif\n+\t\t\t\ttls_mode = AFCD_TLS13;\n+\t\t\t} else {\n+\t\t\t\twpa_printf(MSG_ERROR,\n+\t\t\t\t\t   \"Invalid TLS version '%s'\", optarg);\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase 'M':\n+\t\t\tuse_mtls = true;\n+\t\t\tbreak;\n+\t\tcase 'c':\n+\t\t\tclient_cert = optarg;\n+\t\t\tbreak;\n+\t\tcase 'k':\n+\t\t\tclient_key = optarg;\n+\t\t\tbreak;\n+\t\tcase 'w':\n+\t\t\tclient_key_pass = optarg;\n+\t\t\tbreak;\n+\t\tcase 'A':\n+\t\t\tcafile = optarg;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tusage();\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+\tif (!url) {\n+\t\tusage();\n+\t\tgoto out;\n+\t}\n+\n+\tif (use_mtls) {\n+\t\tif (!client_cert) {\n+\t\t\twpa_printf(MSG_ERROR,\n+\t\t\t\t   \"mTLS requested but client certificate(-c) \"\n+\t\t\t\t   \"is missing\");\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (tls_mode == AFCD_TLS12)\n+\t\t\ttls_mode = AFCD_TLS12_MTLS;\n+\t\telse if (tls_mode == AFCD_TLS13)\n+\t\t\ttls_mode = AFCD_TLS13_MTLS;\n+\t}\n+\n+\tif (daemonize && os_daemonize(pid_file)) {\n+\t\twpa_printf(MSG_ERROR, \"daemon: %s\", strerror(errno));\n+\t\tgoto out;\n+\t}\n+\n+\tsignal(SIGTERM, handle_term);\n+\tsignal(SIGINT, handle_term);\n+\n+\tret = afcd_server_run();\n+out:\n+\tif (pid_file)\n+\t\tos_daemonize_terminate(pid_file);\n+\tos_program_deinit();\n+\n+\treturn ret;\n+}\n",
    "prefixes": [
        "v11",
        "2/7"
    ]
}