From nobody Thu Oct 2 23:47:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D69F630E0ED; Wed, 10 Sep 2025 06:05:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757484317; cv=none; b=Qzl1fn77vvH/FnJH1dRvfuxDxFgGaXepj6bghd58xcuDJhGxF0z/lZzTzagNOjuA5uh+zQPRjt0CVjON2EJUjZwL8LeEOCHrqSgejkffInH4f0x1OTISgmch1euR0xzsbJVWz0FXh3qIWq7PcJN2GL73u5pd1b4dk65Q40F3LtE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757484317; c=relaxed/simple; bh=7jkGwc8sJb5bE4Z0FuNn78xdbtlCemUTIWLBt8xL5Ps=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pl/NciGXP0vuCmHgMfkRfeV7gDS24nmvcrun3pphbgdlinBqVA9Hm5mZ1ag1X7oem4uJhAP2sUYtAsxN1cBfF2IU7o6yHnupQQi5iypiB8aVpO67Pp5FqtOHFRKzmcPLrITkZiDQtJwX+FXfzS+2PswE8Lwpk0szMSR+HFEMLrg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fPd7Q+5s; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fPd7Q+5s" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 38ADFC4CEFA; Wed, 10 Sep 2025 06:05:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757484317; bh=7jkGwc8sJb5bE4Z0FuNn78xdbtlCemUTIWLBt8xL5Ps=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fPd7Q+5sguJgA6pWJDPefhJ173WiMI3vpAEGMaCwsn3hYsjkt8hh+mmruxtgAJD6Q +e37IbDxB6Rj6YhAqKqc66ldOVSPbw+ww+k2g1wemvCygR3UXcCAZ5E2OHHJDvVO89 eJfCa7MFBFO2vrizaxJmj2JxGOTA75txbga4WYELDlqCkVEXVC6+e/+d4iuJ/rmA4Q 3hjf8WcO+6zS3c+0r4y01lN4qnwKSbb9H1vWN299Mo75qYMULUc9ATqUAWOustxoZD SdrhhErC237jwLbiC3DOwcLjrzW3JZqNHo68MFHWw8Q1kZctg7IMiMlaiEhOh3J+WO w0xHtAOX0ihpw== From: Vincent Mailhol Date: Wed, 10 Sep 2025 15:03:45 +0900 Subject: [PATCH v2 20/20] can: netlink: add userland error messages Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250910-canxl-netlink-prep-v2-20-f128d4083721@kernel.org> References: <20250910-canxl-netlink-prep-v2-0-f128d4083721@kernel.org> In-Reply-To: <20250910-canxl-netlink-prep-v2-0-f128d4083721@kernel.org> To: Marc Kleine-Budde , Oliver Hartkopp Cc: Vincent Mailhol , =?utf-8?q?St=C3=A9phane_Grosjean?= , Robert Nawrath , Minh Le , Duy Nguyen , linux-can@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6027; i=mailhol@kernel.org; h=from:subject:message-id; bh=7jkGwc8sJb5bE4Z0FuNn78xdbtlCemUTIWLBt8xL5Ps=; b=owGbwMvMwCV2McXO4Xp97WbG02pJDBkHRX49EJB6vOvW676kA7u/yjW/sK1uUF9cEvT5ouJH1 W1HHfg/dJSyMIhxMciKKbIsK+fkVugo9A479NcSZg4rE8gQBi5OAZhIxjtGht2yfGfsIxxj3k6Q dnaKmplcHvv30onEo5YzZqizaZlPW8nwP29WnfJ9PYkoodMTVnCX/frrpuOv6lHNFbfgaJzCdQd 7fgA= X-Developer-Key: i=mailhol@kernel.org; a=openpgp; fpr=ED8F700574E67F20E574E8E2AB5FEB886DBB99C2 Use NL_SET_ERR_MSG() and NL_SET_ERR_MSG_FMT() to return meaningful error messages to the userland whenever a -EOPNOTSUPP error is returned due to a failed validation of the CAN netlink arguments. Signed-off-by: Vincent Mailhol --- drivers/net/can/dev/netlink.c | 82 ++++++++++++++++++++++++++++++++-------= ---- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 48a74808dbc881d1d46ff7d03d347ddb8af3d16c..d4f13701e719ca52e41188c7e6d= 989d00bc70073 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -63,15 +63,23 @@ static int can_validate_tdc(struct nlattr *data_tdc, bool tdc_auto =3D tdc_flags & CAN_CTRLMODE_TDC_AUTO_MASK; int err; =20 - /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */ - if (tdc_auto && tdc_manual) + if (tdc_auto && tdc_manual) { + NL_SET_ERR_MSG(extack, + "TDC manual and auto modes are mutually exclusive"); return -EOPNOTSUPP; + } =20 /* If one of the CAN_CTRLMODE_TDC_* flag is set then TDC * must be set and vice-versa */ - if ((tdc_auto || tdc_manual) !=3D !!data_tdc) + if ((tdc_auto || tdc_manual) && !data_tdc) { + NL_SET_ERR_MSG(extack, "TDC parameters are missing"); return -EOPNOTSUPP; + } + if (!(tdc_auto || tdc_manual) && data_tdc) { + NL_SET_ERR_MSG(extack, "TDC mode (auto or manual) is missing"); + return -EOPNOTSUPP; + } =20 /* If providing TDC parameters, at least TDCO is needed. TDCV * is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set @@ -85,15 +93,23 @@ static int can_validate_tdc(struct nlattr *data_tdc, return err; =20 if (tb_tdc[IFLA_CAN_TDC_TDCV]) { - if (tdc_auto) + if (tdc_auto) { + NL_SET_ERR_MSG(extack, + "TDCV is incompatible with TDC auto mode"); return -EOPNOTSUPP; + } } else { - if (tdc_manual) + if (tdc_manual) { + NL_SET_ERR_MSG(extack, + "TDC manual mode requires TDCV"); return -EOPNOTSUPP; + } } =20 - if (!tb_tdc[IFLA_CAN_TDC_TDCO]) + if (!tb_tdc[IFLA_CAN_TDC_TDCO]) { + NL_SET_ERR_MSG(extack, "TDCO is missing"); return -EOPNOTSUPP; + } } =20 return 0; @@ -104,6 +120,7 @@ static int can_validate_databittiming(struct nlattr *da= ta[], int ifla_can_data_bittiming, u32 flags) { struct nlattr *data_tdc; + const char *type; u32 tdc_flags; bool is_on; int err; @@ -119,18 +136,31 @@ static int can_validate_databittiming(struct nlattr *= data[], data_tdc =3D data[IFLA_CAN_TDC]; tdc_flags =3D flags & CAN_CTRLMODE_FD_TDC_MASK; is_on =3D flags & CAN_CTRLMODE_FD; + type =3D "FD"; } else { return -EOPNOTSUPP; /* Place holder for CAN XL */ } =20 if (is_on) { - if (!data[IFLA_CAN_BITTIMING] || !data[ifla_can_data_bittiming]) + if (!data[IFLA_CAN_BITTIMING] || !data[ifla_can_data_bittiming]) { + NL_SET_ERR_MSG_FMT(extack, + "Provide both nominal and %s data bittiming", + type); return -EOPNOTSUPP; - } - - if (data[ifla_can_data_bittiming] || data_tdc) { - if (!is_on) + } + } else { + if (data[ifla_can_data_bittiming]) { + NL_SET_ERR_MSG_FMT(extack, + "%s data bittiming requires CAN %s", + type, type); return -EOPNOTSUPP; + } + if (data_tdc) { + NL_SET_ERR_MSG_FMT(extack, + "%s TDC requires CAN %s", + type, type); + return -EOPNOTSUPP; + } } =20 err =3D can_validate_bittiming(data, extack, ifla_can_data_bittiming); @@ -177,8 +207,7 @@ static int can_ctrlmode_changelink(struct net_device *d= ev, { struct can_priv *priv =3D netdev_priv(dev); struct can_ctrlmode *cm; - u32 maskedflags; - u32 ctrlstatic; + u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing; =20 if (!data[IFLA_CAN_CTRLMODE]) return 0; @@ -188,20 +217,28 @@ static int can_ctrlmode_changelink(struct net_device = *dev, return -EBUSY; =20 cm =3D nla_data(data[IFLA_CAN_CTRLMODE]); - maskedflags =3D cm->flags & cm->mask; ctrlstatic =3D can_get_static_ctrlmode(priv); + maskedflags =3D cm->flags & cm->mask; + notsupp =3D maskedflags & ~(priv->ctrlmode_supported | ctrlstatic); + ctrlstatic_missing =3D (maskedflags & ctrlstatic) ^ ctrlstatic; =20 - /* check whether provided bits are allowed to be passed */ - if (maskedflags & ~(priv->ctrlmode_supported | ctrlstatic)) + if (notsupp) { + NL_SET_ERR_MSG_FMT(extack, + "requested control mode %s not supported", + can_get_ctrlmode_str(notsupp)); return -EOPNOTSUPP; + } =20 /* do not check for static fd-non-iso if 'fd' is disabled */ if (!(maskedflags & CAN_CTRLMODE_FD)) ctrlstatic &=3D ~CAN_CTRLMODE_FD_NON_ISO; =20 - /* make sure static options are provided by configuration */ - if ((maskedflags & ctrlstatic) !=3D ctrlstatic) + if (ctrlstatic_missing) { + NL_SET_ERR_MSG_FMT(extack, + "missing required %s static control mode", + can_get_ctrlmode_str(ctrlstatic_missing)); return -EOPNOTSUPP; + } =20 /* If a top dependency flag is provided, reset all its dependencies */ if (cm->mask & CAN_CTRLMODE_FD) @@ -234,8 +271,10 @@ static int can_tdc_changelink(struct data_bittiming_pa= rams *dbt_params, const struct can_tdc_const *tdc_const =3D dbt_params->tdc_const; int err; =20 - if (!tdc_const) + if (!tdc_const) { + NL_SET_ERR_MSG(extack, "The device does not support TDC"); return -EOPNOTSUPP; + } =20 err =3D nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla, can_tdc_policy, extack); @@ -450,8 +489,11 @@ static int can_changelink(struct net_device *dev, stru= ct nlattr *tb[], const unsigned int num_term =3D priv->termination_const_cnt; unsigned int i; =20 - if (!priv->do_set_termination) + if (!priv->do_set_termination) { + NL_SET_ERR_MSG(extack, + "Termination is not configurable on this device"); return -EOPNOTSUPP; + } =20 /* check whether given value is supported by the interface */ for (i =3D 0; i < num_term; i++) { --=20 2.49.1