From patchwork Wed Dec 27 06:09:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 13505150 Received: from mail-oa1-f53.google.com (mail-oa1-f53.google.com [209.85.160.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2874146BF for ; Wed, 27 Dec 2023 06:10:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OANzXDy/" Received: by mail-oa1-f53.google.com with SMTP id 586e51a60fabf-204500454fcso1719439fac.3 for ; Tue, 26 Dec 2023 22:10:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703657441; x=1704262241; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=TyUB8iLFP2aBxVFbLQDQBKLgvthr3mcDBpUWMEG+KFs=; b=OANzXDy/FUzTKw7Y5CJE8NYtCrv0/dEm2On/xWftB4LX5ICtGomdUoMvz1qTmKde8d 42jrZ7D1SSm+uCXwJT1qesfmxKofvPRBJ6HhkZdd1OECDzg/1i3qu/U0Q+bbRozvobGP AbavWesZo09qOZfqM8K3USFwj8vuE/yCb2L7qCEyN8RW/seCfA8DvYYxCZazxVB0XvbO mq9d0seMlheZZ54/JnoGhiH+7DWtSAK+kZExSGovyTrA8XDC+q0mMCNcCtC453iwg67F nzQqdep9rXyY2kaVtCFBxpBsYnqPPtWNCKj66st/qqyxIrzuyb/FWc0dzWSS0K3Ne3BP bM+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703657441; x=1704262241; 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=TyUB8iLFP2aBxVFbLQDQBKLgvthr3mcDBpUWMEG+KFs=; b=iKik54dN1XKIhyFZemRQnGOiRMNr4I0O0Srh/XMQZ0XrVvCufEXnIHvEQASgZq1IMl /BnE3IEsmSy7iDrOyRvYuLf7jNwyp7yxA4a8t1Lfm41imky37GWv2fJ+BhjIrkA8Hy89 qE/3emyJma2GnAfkM7pymfrA6/tOOT99VTJXDcjYnLhT9ViNIISEBbLCR2uEN9uuR7Pp HxVQICReHvyUlIL3mJCyZ1AA5hSO+oYIXAkzNd4wSVJWjA+Wn/+b9DOc+kcZJvkX+dcK 9VJkrJ+t8O+96iHZcH3kE9tFU34bGL+ukNuiK/Fb4SPWXCA/w7OuBne6GWPRj5jwy8QZ 3Htg== X-Gm-Message-State: AOJu0Yzg7XQfngfLXY7FEYQ8QiG8NfnLw8blyHIq7hP/2gsuKXq9hHv6 +T11tyGAgC0uq9p3BO1eFjNwUUZXmR0= X-Google-Smtp-Source: AGHT+IGw4U9g4qW4QBdB90rA/ib0GVWpJociP/fvwFlg+B6YVv3EJVVHO8GkhvQfFWs7uTkcB8kx0A== X-Received: by 2002:a05:6870:818d:b0:203:5afb:4b06 with SMTP id k13-20020a056870818d00b002035afb4b06mr5025447oae.5.1703657441001; Tue, 26 Dec 2023 22:10:41 -0800 (PST) Received: from localhost.localdomain (216.106.68.145.reverse.socket.net. [216.106.68.145]) by smtp.gmail.com with ESMTPSA id vs7-20020a056871a10700b002032bb7895fsm3048841oab.55.2023.12.26.22.10.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Dec 2023 22:10:40 -0800 (PST) From: Denis Kenzior To: iwd@lists.linux.dev Cc: Denis Kenzior Subject: [PATCH 1/5] monitor: Remove unused code path Date: Wed, 27 Dec 2023 00:09:46 -0600 Message-ID: <20231227060954.103572-1-denkenz@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 nlmon_print_genl invokes genl_ctrl when a generic netlink control message is encountered. genl_ctrl() tries to filter nl80211 family appearance messages and setup nlmon->id with the extracted family id. However, the id is already provided inside main.c by using nlmon_open, and no control messages are processed by nlmon in 'capture' mode (-r command line argument not passed) since all genl messages go through nlmon_message() path instead. --- monitor/nlmon.c | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/monitor/nlmon.c b/monitor/nlmon.c index ed40264bacd6..7f8ecdaa1996 100644 --- a/monitor/nlmon.c +++ b/monitor/nlmon.c @@ -7359,35 +7359,6 @@ void nlmon_destroy(struct nlmon *nlmon) l_free(nlmon); } -static void genl_ctrl(struct nlmon *nlmon, const void *data, uint32_t len) -{ - const struct genlmsghdr *genlmsg = data; - const struct nlattr *nla; - char name[GENL_NAMSIZ]; - uint16_t id = 0; - - if (genlmsg->cmd != CTRL_CMD_NEWFAMILY) - return; - - for (nla = data + GENL_HDRLEN; NLA_OK(nla, len); - nla = NLA_NEXT(nla, len)) { - switch (nla->nla_type & NLA_TYPE_MASK) { - case CTRL_ATTR_FAMILY_ID: - id = *((uint16_t *) NLA_DATA(nla)); - break; - case CTRL_ATTR_FAMILY_NAME: - strncpy(name, NLA_DATA(nla), GENL_NAMSIZ - 1); - break; - } - } - - if (id == 0) - return; - - if (!strcmp(name, NL80211_GENL_NAME)) - nlmon->id = id; -} - static const char *scope_to_string(uint8_t scope) { switch (scope) { @@ -8208,10 +8179,9 @@ void nlmon_print_genl(struct nlmon *nlmon, const struct timeval *tv, for (nlmsg = data; NLMSG_OK(nlmsg, size); nlmsg = NLMSG_NEXT(nlmsg, size)) { if (nlmsg->nlmsg_type == GENL_ID_CTRL) - genl_ctrl(nlmon, NLMSG_DATA(nlmsg), - NLMSG_PAYLOAD(nlmsg, 0)); - else - nlmon_message(nlmon, tv, NULL, nlmsg); + continue; + + nlmon_message(nlmon, tv, NULL, nlmsg); } } From patchwork Wed Dec 27 06:09:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 13505151 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8EDB4C9F for ; Wed, 27 Dec 2023 06:10:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RD5YdU3r" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-6dbb650ad59so3120479a34.0 for ; Tue, 26 Dec 2023 22:10:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703657441; x=1704262241; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7uBdQQdJd+ZqxAmYPvLnInlpThFDN9Oc3DsIxNjHPCw=; b=RD5YdU3rSFKCZjy338rAz2qNWQgCWD8cRGl04Av985Wt4mSId0HmZH9uv04/7Z8F2d 01T47o8LZdKmJqrMIBlABaPNbnx6KGMNy0Kfvac2nJQThTyw/xlJURT9gs5xTeNQmOQP jmkUIx94fg9PNwQmWex10H1uu/6Mq27tNlbMB4lWznc2wRJW5uKAIMZIWZx6mFBacmr0 HmCQqBjDtt/y8hrq629GWC97pUPdNi62/xcGd/MPpQCgMfB4Fap3hS5+hjP89RUW8ZeC PwZUv/QGJ8tFqAzHk/KUjHU6huHcMzqaccWJUpYUs7wmWrJhP82xjvAWsfaE3cmLkZJ5 Zi2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703657441; x=1704262241; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7uBdQQdJd+ZqxAmYPvLnInlpThFDN9Oc3DsIxNjHPCw=; b=JjdQI5RtwxcZ5cQkuMt1BfE/K0vhmIsFsrLkeeO6YcVAR0i/MZXrp5+f5BHRXEMlIC TDh5Slt1JR7gMcKoz3VsIHWA7iaUrrlapSHHiUd74m3s6nv47+8UphI776RB/CI/o+yl M12ZuSsJSSQ718ffXx0gAAEQnHyWiwTO8xY5USQRZHtNQTxr5KMXnlY9bPzRv4d4YLX9 7vn4S6ARXDkEGN7LJN/2omuA4cjgqsLrIMsZRmt26gCH2iaHtg7NOKAZq0//v7Bu7nRA 1RgFuTa3XNaZnU6piCCcgJqV7qLRTDY/r9IxCzdqBXklLbnd5ea/BzFKHG1kG3YZtjb/ C7Rg== X-Gm-Message-State: AOJu0YyQifZAgeCTCOgBxe+XRGWhNGQSMovVYUmOf3jCo6V1nKvk0orC 8zoWJocQNr1pcqg7Gen8OR96DXhIXgY= X-Google-Smtp-Source: AGHT+IExjZcUqK+6Ny+T87zKaNP+vUUURh105ikWAjPJN9d3o2wYWtw8chUma6LiRoLY17fCmT+SzA== X-Received: by 2002:a05:6870:c1d1:b0:204:508c:efc7 with SMTP id i17-20020a056870c1d100b00204508cefc7mr4308385oad.49.1703657441640; Tue, 26 Dec 2023 22:10:41 -0800 (PST) Received: from localhost.localdomain (216.106.68.145.reverse.socket.net. [216.106.68.145]) by smtp.gmail.com with ESMTPSA id vs7-20020a056871a10700b002032bb7895fsm3048841oab.55.2023.12.26.22.10.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Dec 2023 22:10:41 -0800 (PST) From: Denis Kenzior To: iwd@lists.linux.dev Cc: Denis Kenzior Subject: [PATCH 2/5] monitor: Remove unused PACKET_AUXDATA handling Date: Wed, 27 Dec 2023 00:09:47 -0600 Message-ID: <20231227060954.103572-2-denkenz@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231227060954.103572-1-denkenz@gmail.com> References: <20231227060954.103572-1-denkenz@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 --- monitor/nlmon.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/monitor/nlmon.c b/monitor/nlmon.c index 7f8ecdaa1996..b4d1f54c7579 100644 --- a/monitor/nlmon.c +++ b/monitor/nlmon.c @@ -7240,7 +7240,6 @@ static void store_message(struct nlmon *nlmon, const struct timeval *tv, } static void nlmon_message(struct nlmon *nlmon, const struct timeval *tv, - const struct tpacket_auxdata *tp, const struct nlmsghdr *nlmsg) { struct nlmon_req *req; @@ -8181,7 +8180,7 @@ void nlmon_print_genl(struct nlmon *nlmon, const struct timeval *tv, if (nlmsg->nlmsg_type == GENL_ID_CTRL) continue; - nlmon_message(nlmon, tv, NULL, nlmsg); + nlmon_message(nlmon, tv, nlmsg); } } @@ -8194,9 +8193,7 @@ static bool nlmon_receive(struct l_io *io, void *user_data) struct iovec iov; struct cmsghdr *cmsg; struct timeval copy_tv; - struct tpacket_auxdata copy_tp; const struct timeval *tv = NULL; - const struct tpacket_auxdata *tp = NULL; uint16_t proto_type; unsigned char buf[8192]; unsigned char control[32]; @@ -8242,12 +8239,6 @@ static bool nlmon_receive(struct l_io *io, void *user_data) memcpy(©_tv, CMSG_DATA(cmsg), sizeof(copy_tv)); tv = ©_tv; } - - if (cmsg->cmsg_level == SOL_PACKET && - cmsg->cmsg_type != PACKET_AUXDATA) { - memcpy(©_tp, CMSG_DATA(cmsg), sizeof(copy_tp)); - tp = ©_tp; - } } nlmsg_len = bytes_read; @@ -8261,7 +8252,7 @@ static bool nlmon_receive(struct l_io *io, void *user_data) nlmon_print_rtnl(nlmon, tv, nlmsg, nlmsg->nlmsg_len); break; case NETLINK_GENERIC: - nlmon_message(nlmon, tv, tp, nlmsg); + nlmon_message(nlmon, tv, nlmsg); break; } } From patchwork Wed Dec 27 06:09:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 13505152 Received: from mail-oi1-f179.google.com (mail-oi1-f179.google.com [209.85.167.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4EFDE5220 for ; Wed, 27 Dec 2023 06:10:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dGrYOWW5" Received: by mail-oi1-f179.google.com with SMTP id 5614622812f47-3bbb78d0eb3so1019991b6e.0 for ; Tue, 26 Dec 2023 22:10:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703657442; x=1704262242; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=o/d10K26YbqkH9HzKw87u2qkJMRbAsTQg4ozYxl/5lE=; b=dGrYOWW5jTEl5104jc5bRiOSzoThsuzIOf5zeGOEzCz4EgLQ7ikJpOVce++jeuzLGA uXghGmT4KzvrRymg69QKYsMKuXfeCjnKDgDR59aF5qHfcSTdZrQ2aeD4F2OsF1hKO6J/ AXKNLtSBJvy5qa15o6Umiz2ZDMcC9jZZcnYsCEytRP58F2hRdZBtJJEL4UbS6/lakcaQ tC1USM1aHMRDZcfkEz4lFVGR6dR/uzF5VJF8FLi+aXFpGeNVLlKWfQqBpQ/DDwJ40+ai RKZqqVF28qHojy82L0C6yxjsFAYBdyfo39TXusX8GErxYi8wKvo+yU9J2xMiGDyL8daS wfEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703657442; x=1704262242; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=o/d10K26YbqkH9HzKw87u2qkJMRbAsTQg4ozYxl/5lE=; b=uo0n1I1n2I4LQkvXvBboyP/LrUqkGXZMXNrVU0M9vY6IGcjJjPBBpaJhl2p/WHu5e0 iEZDOpeYeZi8+HXQJbUmFTrLhZ14wRM2GgVMZFTTlG0EmshnQ0MmCVpk9RWSDWtw7nij 0jlL3CkelMfOmHbENy09gtIvgjJi4cEt/IU1eD9/Lqj1YdTYrOTrSbXCMLZGQWLiOhrm m1bbfnqGEhL0pqmL0Xl1fUxc+NJW3KFNTWLfMbsu3EV51BM4acf3IM240deuWIjzIkWP vzAfxY/OBVgPTkVcOoLNlb0ojoedxCBIYOX9uZkfBds+ZSUvRCCbSYCyw+7aaNj3FGZR SgBA== X-Gm-Message-State: AOJu0YzaQEKmyUt2nfVlHnO3Q0u6wRqHWoFbix8yVdDVuHCbcRlBYVY4 5N1c5GcpAf+uy8rV5wSNfYhH56T/S6A= X-Google-Smtp-Source: AGHT+IGy53GstL+3Jv3MryC3qR99IQ2vmrUylGhYdAeXKTgKbQYRZ2XDHLPDrnCvTqIszrq9eNfe3w== X-Received: by 2002:a05:6870:1610:b0:203:bb03:15d0 with SMTP id b16-20020a056870161000b00203bb0315d0mr9085202oae.9.1703657442115; Tue, 26 Dec 2023 22:10:42 -0800 (PST) Received: from localhost.localdomain (216.106.68.145.reverse.socket.net. [216.106.68.145]) by smtp.gmail.com with ESMTPSA id vs7-20020a056871a10700b002032bb7895fsm3048841oab.55.2023.12.26.22.10.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Dec 2023 22:10:41 -0800 (PST) From: Denis Kenzior To: iwd@lists.linux.dev Cc: Denis Kenzior Subject: [PATCH 3/5] monitor: Use nlmon_print_* inside nlmon_receive Date: Wed, 27 Dec 2023 00:09:48 -0600 Message-ID: <20231227060954.103572-3-denkenz@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231227060954.103572-1-denkenz@gmail.com> References: <20231227060954.103572-1-denkenz@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The current implementation inside nlmon_receive is asymmetrical. RTNL packets are printed using nlmon_print_rtnl while GENL packets are printed using nlmon_message. nlmon_print_genl and nlmon_print_rtnl already handle iterating over data containing multiple messages, and are used by nlmon started in reader mode. Use these for better symmetry inside nlmon_receive. While here, move store_netlink() call into nlmon_print_rtnl. This makes handling of PCAP output symmetrical for both RTNL and GENL packets. This also fixes a possibility where only the first message of a multi-RTNL packet would be stored. --- monitor/nlmon.c | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/monitor/nlmon.c b/monitor/nlmon.c index b4d1f54c7579..72cd8ca7a05c 100644 --- a/monitor/nlmon.c +++ b/monitor/nlmon.c @@ -7280,12 +7280,6 @@ static void nlmon_message(struct nlmon *nlmon, const struct timeval *tv, return; } - if (!nlmon->read && nlmsg->nlmsg_type != nlmon->id) { - if (nlmsg->nlmsg_type == GENL_ID_CTRL) - store_message(nlmon, tv, nlmsg); - return; - } - if (nlmsg->nlmsg_flags & NLM_F_REQUEST) { const struct genlmsghdr *genlmsg = NLMSG_DATA(nlmsg); uint32_t flags = nlmsg->nlmsg_flags & ~NLM_F_REQUEST; @@ -8137,13 +8131,15 @@ void nlmon_print_rtnl(struct nlmon *nlmon, const struct timeval *tv, int64_t aligned_size = NLMSG_ALIGN(size); const struct nlmsghdr *nlmsg; - if (nlmon->nortnl) - return; - update_time_offset(tv); for (nlmsg = data; NLMSG_OK(nlmsg, aligned_size); nlmsg = NLMSG_NEXT(nlmsg, aligned_size)) { + store_netlink(nlmon, tv, NETLINK_ROUTE, nlmsg); + + if (nlmon->nortnl) + continue; + switch (nlmsg->nlmsg_type) { case NLMSG_NOOP: case NLMSG_OVERRUN: @@ -8177,7 +8173,12 @@ void nlmon_print_genl(struct nlmon *nlmon, const struct timeval *tv, for (nlmsg = data; NLMSG_OK(nlmsg, size); nlmsg = NLMSG_NEXT(nlmsg, size)) { - if (nlmsg->nlmsg_type == GENL_ID_CTRL) + if (nlmsg->nlmsg_type == GENL_ID_CTRL) { + store_message(nlmon, tv, nlmsg); + continue; + } + + if (!nlmon->read && nlmsg->nlmsg_type != nlmon->id) continue; nlmon_message(nlmon, tv, nlmsg); @@ -8187,7 +8188,6 @@ void nlmon_print_genl(struct nlmon *nlmon, const struct timeval *tv, static bool nlmon_receive(struct l_io *io, void *user_data) { struct nlmon *nlmon = user_data; - struct nlmsghdr *nlmsg; struct msghdr msg; struct sockaddr_ll sll; struct iovec iov; @@ -8198,7 +8198,6 @@ static bool nlmon_receive(struct l_io *io, void *user_data) unsigned char buf[8192]; unsigned char control[32]; ssize_t bytes_read; - int64_t nlmsg_len; int fd; fd = l_io_get_fd(io); @@ -8241,20 +8240,13 @@ static bool nlmon_receive(struct l_io *io, void *user_data) } } - nlmsg_len = bytes_read; - - for (nlmsg = iov.iov_base; NLMSG_OK(nlmsg, nlmsg_len); - nlmsg = NLMSG_NEXT(nlmsg, nlmsg_len)) { - switch (proto_type) { - case NETLINK_ROUTE: - store_netlink(nlmon, tv, proto_type, nlmsg); - - nlmon_print_rtnl(nlmon, tv, nlmsg, nlmsg->nlmsg_len); - break; - case NETLINK_GENERIC: - nlmon_message(nlmon, tv, nlmsg); - break; - } + switch (proto_type) { + case NETLINK_ROUTE: + nlmon_print_rtnl(nlmon, tv, iov.iov_base, bytes_read); + break; + case NETLINK_GENERIC: + nlmon_print_genl(nlmon, tv, iov.iov_base, bytes_read); + break; } return true; From patchwork Wed Dec 27 06:09:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 13505153 Received: from mail-oa1-f50.google.com (mail-oa1-f50.google.com [209.85.160.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0817E46BF for ; Wed, 27 Dec 2023 06:10:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EJalIaFp" Received: by mail-oa1-f50.google.com with SMTP id 586e51a60fabf-20389f2780fso4210934fac.2 for ; Tue, 26 Dec 2023 22:10:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703657443; x=1704262243; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rG9LkBoL9ME55EULuhkRZC+KHE7gMJYNaTaCrK3SS+g=; b=EJalIaFpEgZp/qFM7jWzhTSGiPKovQXTIUm1H5o5wWpSPu2D8ld/zV48EurcRwM9Fp ry4QURFePfjWIW75bQJ5uci63xKu8fDgLU2qIKMm8DHl+pVzUZKO5zx1N2jE5/EMfSnn xtFF/ywDWc6rHWviCUvzWbWH1XpszoUhSNQTKewTHdUrotDPZbNjGoW+RDpaJHka9gsY JIs30g98+KruP5+QKDn3k3eBiPdNA/8nnCwhIpDe+MQQX3LvEJepAp9tMw0B+/VcWRiE Wvlw1/bN9LZYn7MEhK8t/WzVjRHIu/witxPP1baM/fPR2aiLmeZyAwGW3hbm1GWOHwRd q4qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703657443; x=1704262243; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rG9LkBoL9ME55EULuhkRZC+KHE7gMJYNaTaCrK3SS+g=; b=L/jVon7hdqY/bj7Zbsl3OzKqqW6plRLFsDq16jfTxtpOAzvhG4enUHe3uBXfF7vMCw VrkAO2kFaaPsmhlmwQSnAkEcRkjTKlNdAWngdLDmq457q6KXRPNbgqKmmbA5SuA1foTI CXiXlqtych1fon++8heamiOYj5ptR+bA49v6x0QVvS4iGD3U6xuryyWVTod9LnOd9r2b txb/X8b5ps0UDWFhGOU80CPF3wUVGu9Fqi0L1gQr3E4jElLOWS0o/mBoEEknPwXDjoyE Qg40k7+BWUsE6QAm/NLZCQ07bfyXj+OteVP9Ll2UegzfTbPs93ezc9UqduQxCMbJudLo +l+w== X-Gm-Message-State: AOJu0Ywc5xCJ1y8EuG5Iu/bnn7v/f+mrsgnktMPSwW7qzbFonTHYBOng N0yH1bGQG5mMRWMnbk7yNuj5HP+hilI= X-Google-Smtp-Source: AGHT+IEdUGH53XpSTpwp4NVy/A6jTPzybcwoBYzi+gLXcUWSwEy80v3gmMX+C8CwylDv9d/IOMyZrQ== X-Received: by 2002:a05:6870:910c:b0:203:adc9:ca3d with SMTP id o12-20020a056870910c00b00203adc9ca3dmr10986404oae.98.1703657442759; Tue, 26 Dec 2023 22:10:42 -0800 (PST) Received: from localhost.localdomain (216.106.68.145.reverse.socket.net. [216.106.68.145]) by smtp.gmail.com with ESMTPSA id vs7-20020a056871a10700b002032bb7895fsm3048841oab.55.2023.12.26.22.10.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Dec 2023 22:10:42 -0800 (PST) From: Denis Kenzior To: iwd@lists.linux.dev Cc: Denis Kenzior Subject: [PATCH 4/5] monitor: Move iwmon reading logic into main.c Date: Wed, 27 Dec 2023 00:09:49 -0600 Message-ID: <20231227060954.103572-4-denkenz@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231227060954.103572-1-denkenz@gmail.com> References: <20231227060954.103572-1-denkenz@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To support multiple nlmon sources, move the logic that reads from iwmon device into main.c instead of nlmon. nlmon.c now becomes agnostic of how the packets are actually obtained. Packets are fed in via high-level APIs such as nlmon_print_rtnl, nlmon_print_genl, nlmon_print_pae. --- monitor/main.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++-- monitor/nlmon.c | 165 +-------------------------------------------- monitor/nlmon.h | 2 +- 3 files changed, 174 insertions(+), 168 deletions(-) diff --git a/monitor/main.c b/monitor/main.c index 0c5f0670c706..e9384e1b884f 100644 --- a/monitor/main.c +++ b/monitor/main.c @@ -32,10 +32,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #ifndef ARPHRD_NETLINK @@ -68,11 +71,160 @@ static struct nlmon_config config; #define NLMON_TYPE "nlmon" #define NLMON_LEN 5 +static bool nlmon_receive(struct l_io *io, void *user_data) +{ + struct nlmon *nlmon = user_data; + struct msghdr msg; + struct sockaddr_ll sll; + struct iovec iov; + struct cmsghdr *cmsg; + struct timeval copy_tv; + const struct timeval *tv = NULL; + uint16_t proto_type; + unsigned char buf[8192]; + unsigned char control[32]; + ssize_t bytes_read; + int fd; + + fd = l_io_get_fd(io); + if (fd < 0) + return false; + + memset(&sll, 0, sizeof(sll)); + + memset(&iov, 0, sizeof(iov)); + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &sll; + msg.msg_namelen = sizeof(sll); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + bytes_read = recvmsg(fd, &msg, 0); + if (bytes_read < 0) { + if (errno != EAGAIN && errno != EINTR) + return false; + + return true; + } + + if (sll.sll_hatype != ARPHRD_NETLINK) + return true; + + proto_type = ntohs(sll.sll_protocol); + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_TIMESTAMP) { + memcpy(©_tv, CMSG_DATA(cmsg), sizeof(copy_tv)); + tv = ©_tv; + } + } + + switch (proto_type) { + case NETLINK_ROUTE: + nlmon_print_rtnl(nlmon, tv, iov.iov_base, bytes_read); + break; + case NETLINK_GENERIC: + nlmon_print_genl(nlmon, tv, iov.iov_base, bytes_read); + break; + } + + return true; +} + +/* + * BPF filter to match skb->dev->type == 824 (ARPHRD_NETLINK) and + * either match skb->protocol == 0x0000 (NETLINK_ROUTE) or match + * skb->protocol == 0x0010 (NETLINK_GENERIC). + */ +static struct sock_filter mon_filter[] = { + { 0x28, 0, 0, 0xfffff01c }, /* ldh #hatype */ + { 0x15, 0, 3, 0x00000338 }, /* jne #824, drop */ + { 0x28, 0, 0, 0xfffff000 }, /* ldh #proto */ + { 0x15, 2, 0, 0000000000 }, /* jeq #0x0000, pass */ + { 0x15, 1, 0, 0x00000010 }, /* jeq #0x0010, pass */ + { 0x06, 0, 0, 0000000000 }, /* drop: ret #0 */ + { 0x06, 0, 0, 0xffffffff }, /* pass: ret #-1 */ +}; + +static const struct sock_fprog mon_fprog = { .len = 7, .filter = mon_filter }; + +static struct l_io *open_packet(const char *name) +{ + struct l_io *io; + struct sockaddr_ll sll; + struct packet_mreq mr; + struct ifreq ifr; + int fd, opt = 1; + + fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (fd < 0) { + perror("Failed to create packet socket"); + return NULL; + } + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + + if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { + perror("Failed to get monitor index"); + close(fd); + return NULL; + } + + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_protocol = htons(ETH_P_ALL); + sll.sll_ifindex = ifr.ifr_ifindex; + + if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) < 0) { + perror("Failed to bind packet socket"); + close(fd); + return NULL; + } + + memset(&mr, 0, sizeof(mr)); + mr.mr_ifindex = ifr.ifr_ifindex; + mr.mr_type = PACKET_MR_ALLMULTI; + + if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, + &mr, sizeof(mr)) < 0) { + perror("Failed to enable all multicast"); + close(fd); + return NULL; + } + + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, + &mon_fprog, sizeof(mon_fprog)) < 0) { + perror("Failed to enable monitor filter"); + close(fd); + return NULL; + } + + if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) { + perror("Failed to enable monitor timestamps"); + close(fd); + return NULL; + } + + io = l_io_new(fd); + + l_io_set_close_on_destroy(io, true); + + return io; +} + struct iwmon_interface { char *ifname; bool exists; struct l_netlink *rtnl; struct l_netlink *genl; + struct l_io *io; }; static struct iwmon_interface monitor_interface = { }; @@ -109,11 +261,23 @@ static void genl_parse(uint16_t type, const void *data, uint32_t len, if (id == 0) return; - if (!strcmp(name, NL80211_GENL_NAME)) { - nlmon = nlmon_open(ifname, id, writer_path, &config); - if (!nlmon) - l_main_quit(); - } + if (strcmp(name, NL80211_GENL_NAME)) + return; + + monitor_interface.io = open_packet(ifname); + if (!monitor_interface.io) + goto failed; + + nlmon = nlmon_open(id, writer_path, &config); + if (!nlmon) + goto failed; + + l_io_set_read_handler(monitor_interface.io, nlmon_receive, nlmon, NULL); + + return; + +failed: + l_main_quit(); } static void genl_notify(uint16_t type, const void *data, @@ -790,6 +954,7 @@ int main(int argc, char *argv[]) exit_status = l_main_run_with_signal(signal_handler, NULL); + l_io_destroy(monitor_interface.io); l_netlink_destroy(monitor_interface.rtnl); l_netlink_destroy(monitor_interface.genl); l_free(monitor_interface.ifname); diff --git a/monitor/nlmon.c b/monitor/nlmon.c index 72cd8ca7a05c..5e88cdf1355e 100644 --- a/monitor/nlmon.c +++ b/monitor/nlmon.c @@ -96,7 +96,6 @@ enum msg_type { struct nlmon { uint16_t id; - struct l_io *io; struct l_io *pae_io; struct l_queue *req_list; struct pcap *pcap; @@ -8185,154 +8184,6 @@ void nlmon_print_genl(struct nlmon *nlmon, const struct timeval *tv, } } -static bool nlmon_receive(struct l_io *io, void *user_data) -{ - struct nlmon *nlmon = user_data; - struct msghdr msg; - struct sockaddr_ll sll; - struct iovec iov; - struct cmsghdr *cmsg; - struct timeval copy_tv; - const struct timeval *tv = NULL; - uint16_t proto_type; - unsigned char buf[8192]; - unsigned char control[32]; - ssize_t bytes_read; - int fd; - - fd = l_io_get_fd(io); - if (fd < 0) - return false; - - memset(&sll, 0, sizeof(sll)); - - memset(&iov, 0, sizeof(iov)); - iov.iov_base = buf; - iov.iov_len = sizeof(buf); - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &sll; - msg.msg_namelen = sizeof(sll); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = control; - msg.msg_controllen = sizeof(control); - - bytes_read = recvmsg(fd, &msg, 0); - if (bytes_read < 0) { - if (errno != EAGAIN && errno != EINTR) - return false; - - return true; - } - - if (sll.sll_hatype != ARPHRD_NETLINK) - return true; - - proto_type = ntohs(sll.sll_protocol); - - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_TIMESTAMP) { - memcpy(©_tv, CMSG_DATA(cmsg), sizeof(copy_tv)); - tv = ©_tv; - } - } - - switch (proto_type) { - case NETLINK_ROUTE: - nlmon_print_rtnl(nlmon, tv, iov.iov_base, bytes_read); - break; - case NETLINK_GENERIC: - nlmon_print_genl(nlmon, tv, iov.iov_base, bytes_read); - break; - } - - return true; -} - -/* - * BPF filter to match skb->dev->type == 824 (ARPHRD_NETLINK) and - * either match skb->protocol == 0x0000 (NETLINK_ROUTE) or match - * skb->protocol == 0x0010 (NETLINK_GENERIC). - */ -static struct sock_filter mon_filter[] = { - { 0x28, 0, 0, 0xfffff01c }, /* ldh #hatype */ - { 0x15, 0, 3, 0x00000338 }, /* jne #824, drop */ - { 0x28, 0, 0, 0xfffff000 }, /* ldh #proto */ - { 0x15, 2, 0, 0000000000 }, /* jeq #0x0000, pass */ - { 0x15, 1, 0, 0x00000010 }, /* jeq #0x0010, pass */ - { 0x06, 0, 0, 0000000000 }, /* drop: ret #0 */ - { 0x06, 0, 0, 0xffffffff }, /* pass: ret #-1 */ -}; - -static const struct sock_fprog mon_fprog = { .len = 7, .filter = mon_filter }; - -static struct l_io *open_packet(const char *name) -{ - struct l_io *io; - struct sockaddr_ll sll; - struct packet_mreq mr; - struct ifreq ifr; - int fd, opt = 1; - - fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (fd < 0) { - perror("Failed to create packet socket"); - return NULL; - } - - strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); - - if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { - perror("Failed to get monitor index"); - close(fd); - return NULL; - } - - memset(&sll, 0, sizeof(sll)); - sll.sll_family = AF_PACKET; - sll.sll_protocol = htons(ETH_P_ALL); - sll.sll_ifindex = ifr.ifr_ifindex; - - if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) < 0) { - perror("Failed to bind packet socket"); - close(fd); - return NULL; - } - - memset(&mr, 0, sizeof(mr)); - mr.mr_ifindex = ifr.ifr_ifindex; - mr.mr_type = PACKET_MR_ALLMULTI; - - if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, - &mr, sizeof(mr)) < 0) { - perror("Failed to enable all multicast"); - close(fd); - return NULL; - } - - if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, - &mon_fprog, sizeof(mon_fprog)) < 0) { - perror("Failed to enable monitor filter"); - close(fd); - return NULL; - } - - if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) { - perror("Failed to enable monitor timestamps"); - close(fd); - return NULL; - } - - io = l_io_new(fd); - - l_io_set_close_on_destroy(io, true); - - return io; -} - void nlmon_print_pae(struct nlmon *nlmon, const struct timeval *tv, uint8_t type, int index, const void *data, uint32_t size) @@ -8460,28 +8311,21 @@ static struct l_io *open_pae(void) return io; } -struct nlmon *nlmon_open(const char *ifname, uint16_t id, const char *pathname, +struct nlmon *nlmon_open(uint16_t id, const char *pathname, const struct nlmon_config *config) { struct nlmon *nlmon; - struct l_io *io, *pae_io; + struct l_io *pae_io; struct pcap *pcap; - io = open_packet(ifname); - if (!io) - return NULL; - pae_io = open_pae(); - if (!pae_io) { - l_io_destroy(io); + if (!pae_io) return NULL; - } if (pathname) { pcap = pcap_create(pathname); if (!pcap) { l_io_destroy(pae_io); - l_io_destroy(io); return NULL; } } else @@ -8490,11 +8334,9 @@ struct nlmon *nlmon_open(const char *ifname, uint16_t id, const char *pathname, nlmon = nlmon_create(id, config); - nlmon->io = io; nlmon->pae_io = pae_io; nlmon->pcap = pcap; - l_io_set_read_handler(nlmon->io, nlmon_receive, nlmon, NULL); l_io_set_read_handler(nlmon->pae_io, pae_receive, nlmon, NULL); wlan_iface_list = l_hashmap_new(); @@ -8507,7 +8349,6 @@ void nlmon_close(struct nlmon *nlmon) if (!nlmon) return; - l_io_destroy(nlmon->io); l_io_destroy(nlmon->pae_io); l_queue_destroy(nlmon->req_list, nlmon_req_free); diff --git a/monitor/nlmon.h b/monitor/nlmon.h index 96958c25b2ba..bb1a7c58bd45 100644 --- a/monitor/nlmon.h +++ b/monitor/nlmon.h @@ -33,7 +33,7 @@ struct nlmon_config { bool read_only; }; -struct nlmon *nlmon_open(const char *ifname, uint16_t id, const char *pathname, +struct nlmon *nlmon_open(uint16_t id, const char *pathname, const struct nlmon_config *config); void nlmon_close(struct nlmon *nlmon); From patchwork Wed Dec 27 06:09:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 13505154 Received: from mail-oa1-f51.google.com (mail-oa1-f51.google.com [209.85.160.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95B1B4C9F for ; Wed, 27 Dec 2023 06:10:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AYQLRzf5" Received: by mail-oa1-f51.google.com with SMTP id 586e51a60fabf-204e1203a22so74918fac.1 for ; Tue, 26 Dec 2023 22:10:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703657443; x=1704262243; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=R5Se5BGCQUSsT2Yvzo8uqyBZrNXRRIs2rsNO8xOD9no=; b=AYQLRzf54S0iBAt0iLfp8s1WSaUcscfOYIfuLZMMD3vvmJ3J+y+BocNUSbw/cg8b5t f3UX9mNFA1HkYEL65gZ8rXra3GrA70LtyNn87vmjkTMVMK5hJN2w488AGkY9Cy611y+E 5sqyDrrmGXQlqAUxyZ/Xu9W4XU4feYyriTKnxD62DZC6LLAnMcyHR8YMuGSCxXcoo1He Xx44ad0LceUIpHLgzpXaom3IRbTp2trq2hNR5tkWY94Hu4oKtKYwg9/EiUai9A2iIg99 ffvA6sZp5Kz5dRJcY2MAMi0Sib2f5iaXk2QWW/FlS1TET4XqPhGbfaWkAF8aH7wPoWzU RC0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703657443; x=1704262243; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=R5Se5BGCQUSsT2Yvzo8uqyBZrNXRRIs2rsNO8xOD9no=; b=JSKEfCbIHEPo6X3CUahRYkEZfymVSxTz/WfOAcFlne7Un5vtS8yvCpk4WildS6fSyN Xr1yJngF/lJw1rcR8XgKLKTCzwfHE6+MxS4bzKjIfplsjOO79WqmR0tzhRnKJ/vvxXNX 8CFa6vqwF0R8ARAl+165fL3ydjdH+no5MtY5qyWki8iiVNrQFgMcSmx8fWDHBKWYGEnj 5yHYJqCSjSZD+/MGvOegTyZSufzz+6zQRPT0GODHCdpEYzZXmSuGgDwSMli7jMO0nFIf az/rET1/i27poLSICXURXDzQ9sOEQqR95wnHYFzHdlEYIgeglj+4eYYbYWO4mUZvl2jv LO7A== X-Gm-Message-State: AOJu0YzBbm3es44XdQ431e02NnX5LyvZG/33QH74drMTrJoEw/wTWRTc Cte1VDTfpNt5910AIvCufLj9nDyXt3Q= X-Google-Smtp-Source: AGHT+IFA1/yTqpSG776Fhs5KJSY1nDRYJsbZhiSKEguZ04sUGt4W5a2NO8qDs44YZ2SwHVCqVXvw7Q== X-Received: by 2002:a05:6870:2192:b0:203:dfdc:a80a with SMTP id l18-20020a056870219200b00203dfdca80amr7084754oae.112.1703657443337; Tue, 26 Dec 2023 22:10:43 -0800 (PST) Received: from localhost.localdomain (216.106.68.145.reverse.socket.net. [216.106.68.145]) by smtp.gmail.com with ESMTPSA id vs7-20020a056871a10700b002032bb7895fsm3048841oab.55.2023.12.26.22.10.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Dec 2023 22:10:43 -0800 (PST) From: Denis Kenzior To: iwd@lists.linux.dev Cc: Denis Kenzior Subject: [PATCH 5/5] RFC: Initial iwtrace utility Date: Wed, 27 Dec 2023 00:09:50 -0600 Message-ID: <20231227060954.103572-5-denkenz@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231227060954.103572-1-denkenz@gmail.com> References: <20231227060954.103572-1-denkenz@gmail.com> Precedence: bulk X-Mailing-List: iwd@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 eBPF based tracing, similar to iwmon. This is meant as an alternative to the nlmon based netlink tracing and can be used on kernels where nlmon might not be available. --- Makefile.am | 46 ++++++--- configure.ac | 11 +++ monitor/iwtrace.bpf.c | 194 +++++++++++++++++++++++++++++++++++++ monitor/iwtrace.c | 218 ++++++++++++++++++++++++++++++++++++++++++ monitor/iwtrace.h | 12 +++ 5 files changed, 466 insertions(+), 15 deletions(-) create mode 100644 monitor/iwtrace.bpf.c create mode 100644 monitor/iwtrace.c create mode 100644 monitor/iwtrace.h diff --git a/Makefile.am b/Makefile.am index 5ed6ab37164b..601db513d1e3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -327,23 +327,39 @@ endif endif if MONITOR +MONITOR_SOURCES = linux/nl80211.h \ + monitor/nlmon.h monitor/nlmon.c \ + monitor/pcap.h monitor/pcap.c \ + monitor/display.h monitor/display.c \ + src/ie.h src/ie.c \ + src/wscutil.h src/wscutil.c \ + src/mpdu.h src/mpdu.c \ + src/util.h src/util.c \ + src/crypto.h src/crypto.c \ + src/watchlist.h src/watchlist.c \ + src/eapolutil.h src/eapolutil.c \ + src/nl80211cmd.h src/nl80211cmd.c \ + src/p2putil.c src/p2putil.h \ + src/anqputil.h src/anqputil.c \ + src/band.h src/band.c bin_PROGRAMS += monitor/iwmon -monitor_iwmon_SOURCES = monitor/main.c linux/nl80211.h \ - monitor/nlmon.h monitor/nlmon.c \ - monitor/pcap.h monitor/pcap.c \ - monitor/display.h monitor/display.c \ - src/ie.h src/ie.c \ - src/wscutil.h src/wscutil.c \ - src/mpdu.h src/mpdu.c \ - src/util.h src/util.c \ - src/crypto.h src/crypto.c \ - src/watchlist.h src/watchlist.c \ - src/eapolutil.h src/eapolutil.c \ - src/nl80211cmd.h src/nl80211cmd.c \ - src/p2putil.c src/p2putil.h \ - src/anqputil.h src/anqputil.c \ - src/band.h src/band.c +if BPF +bin_PROGRAMS += monitor/iwtrace + +monitor/iwtrace.bpf.o: monitor/iwtrace.bpf.c + clang -g -O2 -target bpf -c monitor/iwtrace.bpf.c -o monitor/iwtrace.tmp.bpf.o + bpftool gen object monitor/iwtrace.bpf.o monitor/iwtrace.tmp.bpf.o + +monitor/iwtrace.skel.h: monitor/iwtrace.bpf.o + bpftool gen skeleton monitor/iwtrace.bpf.o > monitor/iwtrace.skel.h + +monitor_iwtrace_SOURCES = monitor/iwtrace.c monitor/iwtrace.h \ + monitor/iwtrace.skel.h $(MONITOR_SOURCES) +monitor_iwtrace_LDADD = $(ell_ldadd) $(LIBBPF_LIBS) +endif + +monitor_iwmon_SOURCES = monitor/main.c $(MONITOR_SOURCES) monitor_iwmon_LDADD = $(ell_ldadd) if MANUAL_PAGES diff --git a/configure.ac b/configure.ac index d84e035c2f5f..bb7bfedcf80f 100644 --- a/configure.ac +++ b/configure.ac @@ -200,6 +200,17 @@ AC_ARG_ENABLE([monitor], AS_HELP_STRING([--disable-monitor], [enable_monitor=${enableval}]) AM_CONDITIONAL(MONITOR, test "${enable_monitor}" != "no") +AC_ARG_ENABLE([bpf], AS_HELP_STRING([--disable-bpf], + [don't enable bpf based tracing]), + [enable_bpf=${enableval}]) +if (test "${enable_bpf}" != "no"); then + PKG_CHECK_MODULES(LIBBPF, libbpf, dummy=yes, + AC_MSG_ERROR(libbpf is required)) + AC_SUBST(LIBBPF_CFLAGS) + AC_SUBST(LIBBPF_LIBS) +fi +AM_CONDITIONAL(BPF, test "${enable_bpf}" != "no") + AC_ARG_ENABLE([dbus-policy], AS_HELP_STRING([--disable-dbus-policy], [don't install D-Bus system policy files]), [enable_dbus_policy=${enableval}]) diff --git a/monitor/iwtrace.bpf.c b/monitor/iwtrace.bpf.c new file mode 100644 index 000000000000..251b54fc2a41 --- /dev/null +++ b/monitor/iwtrace.bpf.c @@ -0,0 +1,194 @@ +/* + * Embedded Linux library + * Copyright (C) 2023 Cruise, LLC + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "iwtrace.h" + +char LICENSE[] SEC("license") = "GPL"; + +struct sock; +struct netlink_ext_ack; + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} rb SEC(".maps"); + +struct sock { + uint16_t sk_protocol; +}; + +struct sk_buff { + unsigned int len, data_len; + unsigned char *data; + struct net_device *dev; + union { + struct sock *sk; + int ip_defrag_offset; + }; +}; + +struct capture_256 { + struct metadata meta; + uint8_t packet[256 - sizeof(struct metadata)]; +} __attribute__ ((packed)); + +struct capture_1k { + struct metadata meta; + uint8_t packet[1024 - sizeof(struct metadata)]; +} __attribute__ ((packed)); + +struct capture_4k { + struct metadata meta; + uint8_t packet[4096 - sizeof(struct metadata)]; +} __attribute__ ((packed)); + +struct capture_8k { + struct metadata meta; + uint8_t packet[8192 - sizeof(struct metadata)]; +} __attribute__ ((packed)); + +struct capture_16k { + struct metadata meta; + uint8_t packet[16384]; +} __attribute__ ((packed)); + +static void metadata_fill(struct metadata *meta, const struct sk_buff *skb) +{ + struct sock *sk = __builtin_preserve_access_index(skb->sk); + + meta->timestamp = bpf_ktime_get_boot_ns(); + meta->len = __builtin_preserve_access_index(skb->len); + meta->protocol = __builtin_preserve_access_index(sk->sk_protocol); +} + +static int capture_common(const struct sk_buff *skb) +{ + uint16_t len = __builtin_preserve_access_index(skb->len); + const void *data = __builtin_preserve_access_index(skb->data); + + /* + * bpf_ringbuf_reserve is currently limited to a known constant + * value, and cannot handle values that are not constant (even if + * bounded). bpf_ringbuf_output might be suitable, but no metadata + * could be prepended if that is used. Another alternative is to use + * a perf buffer, but it is per-CPU and might result in packets being + * processed out of order. We trick the validator by using several + * well known structure sizes (256/1k/4k/8k/16k) in order to save on + * memory space, but the resultant program is larger than it would be + * if dynamic sizing was supported. + */ + if (len <= 256 - sizeof(struct metadata)) { + struct capture_256 *c256 = bpf_ringbuf_reserve(&rb, + sizeof(struct capture_256), 0); + + if (!c256) + return 0; + + metadata_fill(&c256->meta, skb); + + if (bpf_probe_read_kernel(c256->packet, len, data) < 0) + bpf_ringbuf_discard(c256, BPF_RB_NO_WAKEUP); + else + bpf_ringbuf_submit(c256, 0); + + return 0; + } + + if (len <= sizeof(struct capture_1k) - sizeof(struct metadata)) { + struct capture_1k *c1k = bpf_ringbuf_reserve(&rb, + sizeof(struct capture_1k), 0); + + if (!c1k) + return 0; + + metadata_fill(&c1k->meta, skb); + + if (bpf_probe_read_kernel(c1k->packet, len, data) < 0) + bpf_ringbuf_discard(c1k, BPF_RB_NO_WAKEUP); + else + bpf_ringbuf_submit(c1k, 0); + + return 0; + } + + if (len <= sizeof(struct capture_4k) - sizeof(struct metadata)) { + struct capture_4k *c4k = bpf_ringbuf_reserve(&rb, + sizeof(struct capture_4k), 0); + + if (!c4k) + return 0; + + metadata_fill(&c4k->meta, skb); + + if (bpf_probe_read_kernel(c4k->packet, len, data) < 0) + bpf_ringbuf_discard(c4k, BPF_RB_NO_WAKEUP); + else + bpf_ringbuf_submit(c4k, 0); + + return 0; + } + + if (len <= sizeof(struct capture_8k) - sizeof(struct metadata)) { + struct capture_8k *c8k = bpf_ringbuf_reserve(&rb, + sizeof(struct capture_8k), 0); + + if (!c8k) + return 0; + + metadata_fill(&c8k->meta, skb); + + if (bpf_probe_read_kernel(c8k->packet, len, data) < 0) + bpf_ringbuf_discard(c8k, BPF_RB_NO_WAKEUP); + else + bpf_ringbuf_submit(c8k, 0); + + return 0; + } + + /* 16384 is the largest packet size for genl currently */ + if (len <= 16384) { + struct capture_16k *c16k = bpf_ringbuf_reserve(&rb, + sizeof(struct capture_16k), 0); + + if (!c16k) + return 0; + + metadata_fill(&c16k->meta, skb); + + if (bpf_probe_read_kernel(c16k->packet, len, data) < 0) + bpf_ringbuf_discard(c16k, BPF_RB_NO_WAKEUP); + else + bpf_ringbuf_submit(c16k, 0); + + return 0; + } + + return 0; +} + +SEC("fentry/__netlink_sendskb") +int BPF_PROG(trace___netlink_sendskb, struct sock *sk, struct sk_buff *skb) +{ + return capture_common(skb); +} + +SEC("fentry/netlink_rcv_skb") +int BPF_PROG(trace_netlink_rcv_skb, struct sk_buff *skb, + int (*cb)(struct sk_buff *, + struct nlmsghdr *, + struct netlink_ext_ack *)) +{ + return capture_common(skb); +} diff --git a/monitor/iwtrace.c b/monitor/iwtrace.c new file mode 100644 index 000000000000..ceff71753463 --- /dev/null +++ b/monitor/iwtrace.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2023 Cruise, LLC + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iwtrace.h" +#include "iwtrace.skel.h" +#include "monitor/nlmon.h" +#include "monitor/pcap.h" +#include "monitor/display.h" + +#include + +static struct iwtrace_bpf *skel; +static struct ring_buffer *rb; +static struct l_io *io; +static struct l_genl *genl; +static struct nlmon_config config; +static const char *writer_path; +static struct nlmon *nlmon; + +#ifndef ARPHRD_NETLINK +#define ARPHRD_NETLINK 824 +#endif + +static int libbpf_print_fn(enum libbpf_print_level level, + const char *format, va_list args) +{ + return vfprintf(stderr, format, args); +} + +static int handle_packet(void *ctx, void *data, size_t size) +{ + struct metadata *meta = data; + struct timeval tv; + + data += sizeof(struct metadata); + + tv.tv_sec = meta->timestamp / L_NSEC_PER_SEC; + tv.tv_usec = (meta->timestamp % L_NSEC_PER_SEC) / L_NSEC_PER_USEC; + + switch (meta->protocol) { + case NETLINK_ROUTE: + nlmon_print_rtnl(nlmon, &tv, data, meta->len); + break; + case NETLINK_GENERIC: + nlmon_print_genl(nlmon, &tv, data, meta->len); + break; + } + + return 0; +} + +static bool ringbuf_receive(struct l_io *io, void *user_data) +{ + ring_buffer__poll(rb, 0); + + return true; +} + +static void nl80211_appeared(const struct l_genl_family_info *info, + void *user_data) +{ + int err; + + err = iwtrace_bpf__attach(skel); + if (err) { + fprintf(stderr, "Unable to attach eBPF program\n"); + goto failed; + } + + rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), + handle_packet, NULL, NULL); + if (!rb) { + fprintf(stderr, "Failed to create ringbuffer\n"); + goto failed; + } + + nlmon = nlmon_open(l_genl_family_info_get_id(info), + writer_path, &config); + if (!nlmon) + goto failed; + + io = l_io_new(bpf_map__fd(skel->maps.rb)); + l_io_set_close_on_destroy(io, false); + l_io_set_read_handler(io, ringbuf_receive, NULL, NULL); + + return; +failed: + l_main_quit(); +} + +static void signal_handler(uint32_t signo, void *user_data) +{ + switch (signo) { + case SIGINT: + case SIGTERM: + l_main_quit(); + break; + } +} + +static void usage(void) +{ + printf("iwtrace - Wireless monitor using eBPF\n" + "Usage:\n"); + printf("\tiwtrace [options]\n"); + printf("Options:\n" + "\t-w, --write Write netlink PCAP trace file\n" + "\t-n, --nortnl Don't show RTNL output\n" + "\t-y, --nowiphy Don't show 'New Wiphy' output\n" + "\t-s, --noscan Don't show scan result output\n" + "\t-e, --noies Don't show IEs except SSID\n" + "\t-h, --help Show help options\n"); +} + +static const struct option main_options[] = { + { "write", required_argument, NULL, 'w' }, + { "nortnl", no_argument, NULL, 'n' }, + { "nowiphy", no_argument, NULL, 'y' }, + { "noscan", no_argument, NULL, 's' }, + { "noies", no_argument, NULL, 'e' }, + { "version", no_argument, NULL, 'v' }, + { "help", no_argument, NULL, 'h' }, + { } +}; + +int main(int argc, char *argv[]) +{ + int exit_status = EXIT_FAILURE; + + for (;;) { + int opt; + + opt = getopt_long(argc, argv, "w:nvhyse", + main_options, NULL); + if (opt < 0) + break; + + switch (opt) { + case 'w': + writer_path = optarg; + break; + case 'n': + config.nortnl = true; + break; + case 'y': + config.nowiphy = true; + break; + case 's': + config.noscan = true; + break; + case 'e': + config.noies = true; + break; + case 'v': + printf("%s\n", VERSION); + return EXIT_SUCCESS; + case 'h': + usage(); + return EXIT_SUCCESS; + default: + return EXIT_FAILURE; + } + } + + if (argc - optind > 0) { + fprintf(stderr, "Invalid command line parameters\n"); + return EXIT_FAILURE; + } + + libbpf_set_print(libbpf_print_fn); + + skel = iwtrace_bpf__open_and_load(); + if (!skel) + return EXIT_FAILURE; + + fprintf(stdout, "Wireless monitor (eBPF) ver %s\n", VERSION); + + if (!l_main_init()) + goto init_failed; + + genl = l_genl_new(); + if (!genl) { + fprintf(stderr, "Failed to open generic netlink socket\n"); + goto genl_failed; + } + + l_genl_request_family(genl, "nl80211", nl80211_appeared, NULL, NULL); + exit_status = l_main_run_with_signal(signal_handler, NULL); + + l_genl_unref(genl); + nlmon_close(nlmon); + l_io_destroy(io); + ring_buffer__free(rb); + +genl_failed: + l_main_exit(); +init_failed: + iwtrace_bpf__destroy(skel); + + return exit_status; +} diff --git a/monitor/iwtrace.h b/monitor/iwtrace.h new file mode 100644 index 000000000000..0df95f2ea989 --- /dev/null +++ b/monitor/iwtrace.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* Copyright (c) 2020 Facebook */ +#ifndef __BOOTSTRAP_H +#define __BOOTSTRAP_H + +struct metadata { + uint64_t timestamp; + uint16_t len; + uint16_t protocol; +} __attribute__ ((packed)); + +#endif /* __BOOTSTRAP_H */