mirror of
https://github.com/linux-can/can-utils.git
synced 2026-11-04 15:31:10 +01:00
Several log messages used format specifiers which did not match the types of the provided arguments (e.g. %d or %i for size_t/ssize_t, %ld for int64_t/time_t and size_t for the '.*' precision). On 64 bit hosts (and for int64_t/time_t on 32 bit hosts) this leads to wrong output or undefined behaviour when the log level is enabled. Additionally the seek response position was compared to the requested offset without le32toh() conversion which fails on big endian hosts. Fix the format specifiers and add the missing le32toh() conversion. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
243 lines
6.2 KiB
C
243 lines
6.2 KiB
C
// SPDX-License-Identifier: LGPL-2.0-only
|
|
// SPDX-FileCopyrightText: 2023 Oleksij Rempel <linux@rempel-privat.de>
|
|
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "isobusfs_cli.h"
|
|
#include "isobusfs_cmn_cm.h"
|
|
|
|
|
|
int isobusfs_cli_volume_status_req(struct isobusfs_priv *priv,
|
|
uint8_t volume_mode,
|
|
uint16_t path_name_length,
|
|
const char *volume_name)
|
|
{
|
|
struct isobusfs_cm_vol_stat_req req;
|
|
size_t req_size;
|
|
int ret;
|
|
|
|
req.fs_function =
|
|
isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
|
|
ISOBUSFS_CM_VOLUME_STATUS_REQ);
|
|
|
|
req.volume_mode = volume_mode;
|
|
req.name_len = htole16(path_name_length);
|
|
req_size = sizeof(req) - sizeof(req.name) + path_name_length;
|
|
|
|
memcpy(req.name, volume_name, path_name_length);
|
|
|
|
ret = isobusfs_send(priv->sock_main, &req, req_size, &priv->tx_buf_log);
|
|
if (ret < 0) {
|
|
ret = -errno;
|
|
pr_warn("failed to send volume status request: %d (%s)", ret, strerror(ret));
|
|
return ret;
|
|
}
|
|
|
|
priv->state = ISOBUSFS_CLI_STATE_WAIT_VOLUME_STATUS;
|
|
|
|
pr_debug("> tx: volume status request");
|
|
return 0;
|
|
}
|
|
|
|
|
|
int isobusfs_cli_property_req(struct isobusfs_priv *priv)
|
|
{
|
|
uint8_t buf[ISOBUSFS_MIN_TRANSFER_LENGH];
|
|
int ret;
|
|
|
|
/* not used space should be filled with 0xff */
|
|
memset(buf, 0xff, ARRAY_SIZE(buf));
|
|
buf[0] = isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
|
|
ISOBUSFS_CM_GET_FS_PROPERTIES);
|
|
|
|
/* send property request */
|
|
ret = isobusfs_send(priv->sock_main, buf, sizeof(buf), &priv->tx_buf_log);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
priv->state = ISOBUSFS_CLI_STATE_WAIT_FS_PROPERTIES;
|
|
|
|
pr_debug("> tx: FS property request");
|
|
return 0;
|
|
}
|
|
|
|
/* ccm section */
|
|
void isobusfs_cli_ccm_init(struct isobusfs_priv *priv)
|
|
{
|
|
struct isobusfs_cm_ccm *ccm = &priv->ccm;
|
|
|
|
ccm->fs_function =
|
|
isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
|
|
ISOBUSFS_CM_F_FS_STATUS);
|
|
ccm->version = 2;
|
|
memset(ccm->reserved, 0xFF, sizeof(ccm->reserved));
|
|
}
|
|
|
|
/**
|
|
* isobusfs_cli_ccm_send - send periodic file server status messages
|
|
* @priv: pointer to the isobusfs_priv structure
|
|
*
|
|
* Returns 0 on success, -1 on errors.
|
|
*/
|
|
int isobusfs_cli_ccm_send(struct isobusfs_priv *priv)
|
|
{
|
|
int64_t time_diff;
|
|
int ret;
|
|
|
|
/* Test if it is proper time to send next status message. */
|
|
time_diff = timespec_diff_ms(&priv->cmn.next_send_time,
|
|
&priv->cmn.last_time);
|
|
if (time_diff > ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
|
/* too early to send next message */
|
|
return 0;
|
|
}
|
|
|
|
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
|
|
pr_warn("too late to send next fs status message: %" PRId64 " ms",
|
|
time_diff);
|
|
}
|
|
|
|
/* Make sure we send the message with the latest stats */
|
|
if (priv->stats.tskey_sch != priv->stats.tskey_ack)
|
|
pr_warn("previous message was not acked");
|
|
|
|
/* send periodic file servers status messages. */
|
|
ret = isobusfs_send(priv->sock_ccm, &priv->ccm, sizeof(priv->ccm),
|
|
&priv->tx_buf_log);
|
|
if (ret < 0) {
|
|
pr_err("sendto() failed: %d (%s)", ret, strerror(ret));
|
|
return ret;
|
|
}
|
|
|
|
pr_debug("> tx: ccm version: %d", priv->ccm.version);
|
|
|
|
priv->cmn.next_send_time = priv->cmn.last_time;
|
|
timespec_add_ms(&priv->cmn.next_send_time, 2000);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* detect if FS is timeout */
|
|
void isobusfs_cli_fs_detect_timeout(struct isobusfs_priv *priv)
|
|
{
|
|
int64_t time_diff;
|
|
|
|
if (!priv->fs_is_active)
|
|
return;
|
|
|
|
time_diff = timespec_diff_ms(&priv->cmn.last_time,
|
|
&priv->fs_last_seen);
|
|
if (time_diff > ISOBUSFS_FS_TIMEOUT) {
|
|
pr_debug("file server timeout");
|
|
priv->fs_is_active = false;
|
|
}
|
|
}
|
|
|
|
/* activate FS status if was not active till now */
|
|
static void isobusfs_cli_fs_activate(struct isobusfs_priv *priv)
|
|
{
|
|
if (priv->fs_is_active)
|
|
return;
|
|
|
|
pr_debug("file server detectet");
|
|
priv->fs_is_active = true;
|
|
}
|
|
|
|
static int isobusfs_cli_rx_fs_status(struct isobusfs_priv *priv,
|
|
struct isobusfs_msg *msg)
|
|
{
|
|
struct isobusfs_cm_fss *fs_status = (void *)msg->buf;
|
|
int ret = 0;
|
|
|
|
if (msg->len != sizeof(*fs_status)) {
|
|
pr_warn("wrong message length: %zd", msg->len);
|
|
return -EINVAL;
|
|
}
|
|
|
|
isobusfs_cli_fs_activate(priv);
|
|
|
|
priv->fs_last_seen = priv->cmn.last_time;
|
|
pr_debug("< rx: fs status: %x, opened files: %d",
|
|
fs_status->status, fs_status->num_open_files);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* process FS properties response */
|
|
static int isobusfs_cli_rx_fs_property_res(struct isobusfs_priv *priv,
|
|
struct isobusfs_msg *msg)
|
|
{
|
|
struct isobusfs_cm_get_fs_props_resp *fs_prop = (void *)msg->buf;
|
|
int ret = 0;
|
|
|
|
if (priv->state != ISOBUSFS_CLI_STATE_WAIT_FS_PROPERTIES) {
|
|
pr_warn("unexpected fs properties response");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (msg->len != sizeof(*fs_prop)) {
|
|
pr_warn("wrong message length: %zd", msg->len);
|
|
return -EINVAL;
|
|
}
|
|
|
|
priv->fs_version = fs_prop->version_number;
|
|
priv->fs_max_open_files = fs_prop->max_open_files;
|
|
priv->fs_caps = fs_prop->fs_capabilities;
|
|
|
|
|
|
pr_debug("< rx: fs properties: version: %d, max open files: %d, caps: %x",
|
|
priv->fs_version, priv->fs_max_open_files, priv->fs_caps);
|
|
|
|
priv->state = ISOBUSFS_CLI_STATE_GET_FS_PROPERTIES_DONE;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* function to handle ISOBUSFS_CM_VOLUME_STATUS_RES */
|
|
static int isobusfs_cli_rx_volume_status_res(struct isobusfs_priv *priv,
|
|
struct isobusfs_msg *msg)
|
|
{
|
|
struct isobusfs_cm_vol_stat_res *vol_status = (void *)msg->buf;
|
|
int ret = 0;
|
|
|
|
if (priv->state != ISOBUSFS_CLI_STATE_WAIT_VOLUME_STATUS) {
|
|
pr_warn("unexpected volume status response");
|
|
return -EINVAL;
|
|
}
|
|
|
|
pr_debug("< rx: volume status: %x, max time before remove %d, error code %d, path name length %d, name %s",
|
|
vol_status->volume_status,
|
|
vol_status->max_time_before_removal,
|
|
vol_status->error_code,
|
|
vol_status->name_len,
|
|
vol_status->name);
|
|
|
|
priv->state = ISOBUSFS_CLI_STATE_VOLUME_STATUS_DONE;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Command group: connection management */
|
|
int isobusfs_cli_rx_cg_cm(struct isobusfs_priv *priv, struct isobusfs_msg *msg)
|
|
{
|
|
int func = isobusfs_buf_to_function(msg->buf);
|
|
int ret = 0;
|
|
|
|
switch (func) {
|
|
case ISOBUSFS_CM_F_FS_STATUS:
|
|
return isobusfs_cli_rx_fs_status(priv, msg);
|
|
case ISOBUSFS_CM_GET_FS_PROPERTIES_RES:
|
|
return isobusfs_cli_rx_fs_property_res(priv, msg);
|
|
case ISOBUSFS_CM_VOLUME_STATUS_RES:
|
|
return isobusfs_cli_rx_volume_status_res(priv, msg);
|
|
default:
|
|
pr_warn("unsupported function: %i", func);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|