提交 ae64438b 编写于 作者: O Oliver Hartkopp 提交者: Marc Kleine-Budde

can: dev: fix skb drop check

In commit a6d190f8 ("can: skb: drop tx skb if in listen only
mode") the priv->ctrlmode element is read even on virtual CAN
interfaces that do not create the struct can_priv at startup. This
out-of-bounds read may lead to CAN frame drops for virtual CAN
interfaces like vcan and vxcan.

This patch mainly reverts the original commit and adds a new helper
for CAN interface drivers that provide the required information in
struct can_priv.

Fixes: a6d190f8 ("can: skb: drop tx skb if in listen only mode")
Reported-by: NDariusz Stojaczyk <Dariusz.Stojaczyk@opensynergy.com>
Cc: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Cc: Max Staudt <max@enpas.org>
Signed-off-by: NOliver Hartkopp <socketcan@hartkopp.net>
Acked-by: NVincent Mailhol <mailhol.vincent@wanadoo.fr>
Link: https://lore.kernel.org/all/20221102095431.36831-1-socketcan@hartkopp.net
Cc: stable@vger.kernel.org # 6.0.x
[mkl: patch pch_can, too]
Signed-off-by: NMarc Kleine-Budde <mkl@pengutronix.de>
上级 3eb3d283
...@@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned int mb, prio; unsigned int mb, prio;
u32 reg_mid, reg_mcr; u32 reg_mid, reg_mcr;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
mb = get_tx_next_mb(priv); mb = get_tx_next_mb(priv);
......
...@@ -457,7 +457,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, ...@@ -457,7 +457,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
struct c_can_tx_ring *tx_ring = &priv->tx; struct c_can_tx_ring *tx_ring = &priv->tx;
u32 idx, obj, cmd = IF_COMM_TX; u32 idx, obj, cmd = IF_COMM_TX;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (c_can_tx_busy(priv, tx_ring)) if (c_can_tx_busy(priv, tx_ring))
......
...@@ -813,7 +813,7 @@ static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb, ...@@ -813,7 +813,7 @@ static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb,
struct can327 *elm = netdev_priv(dev); struct can327 *elm = netdev_priv(dev);
struct can_frame *frame = (struct can_frame *)skb->data; struct can_frame *frame = (struct can_frame *)skb->data;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* We shouldn't get here after a hardware fault: /* We shouldn't get here after a hardware fault:
......
...@@ -429,7 +429,7 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -429,7 +429,7 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct cc770_priv *priv = netdev_priv(dev); struct cc770_priv *priv = netdev_priv(dev);
unsigned int mo = obj2msgobj(CC770_OBJ_TX); unsigned int mo = obj2msgobj(CC770_OBJ_TX);
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); netif_stop_queue(dev);
......
...@@ -600,7 +600,7 @@ static netdev_tx_t ctucan_start_xmit(struct sk_buff *skb, struct net_device *nde ...@@ -600,7 +600,7 @@ static netdev_tx_t ctucan_start_xmit(struct sk_buff *skb, struct net_device *nde
bool ok; bool ok;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (unlikely(!CTU_CAN_FD_TXTNF(priv))) { if (unlikely(!CTU_CAN_FD_TXTNF(priv))) {
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include <linux/can/netlink.h>
#include <linux/module.h> #include <linux/module.h>
#define MOD_DESC "CAN device driver interface" #define MOD_DESC "CAN device driver interface"
...@@ -337,8 +336,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb) ...@@ -337,8 +336,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */ /* Drop a given socketbuffer if it does not contain a valid CAN frame. */
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb) bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
{ {
struct can_priv *priv = netdev_priv(dev);
switch (ntohs(skb->protocol)) { switch (ntohs(skb->protocol)) {
case ETH_P_CAN: case ETH_P_CAN:
if (!can_is_can_skb(skb)) if (!can_is_can_skb(skb))
...@@ -359,13 +356,8 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb) ...@@ -359,13 +356,8 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
goto inval_skb; goto inval_skb;
} }
if (!can_skb_headroom_valid(dev, skb)) { if (!can_skb_headroom_valid(dev, skb))
goto inval_skb; goto inval_skb;
} else if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
netdev_info_once(dev,
"interface in listen only mode, dropping skb\n");
goto inval_skb;
}
return false; return false;
......
...@@ -742,7 +742,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de ...@@ -742,7 +742,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16); u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16);
int i; int i;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); netif_stop_queue(dev);
......
...@@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb, ...@@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
unsigned long flags; unsigned long flags;
u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT; u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* Trying to transmit in silent mode will generate error interrupts, but /* Trying to transmit in silent mode will generate error interrupts, but
......
...@@ -860,7 +860,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb, ...@@ -860,7 +860,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb,
u32 txst, txid, txdlc; u32 txst, txid, txdlc;
int i; int i;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* Check if the TX buffer is full */ /* Check if the TX buffer is full */
......
...@@ -1693,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1693,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
void __iomem *desc_addr; void __iomem *desc_addr;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock_irqsave(&mod->lock, flags); spin_lock_irqsave(&mod->lock, flags);
......
...@@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, ...@@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
int nwords; int nwords;
u8 count; u8 count;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
......
...@@ -1721,7 +1721,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, ...@@ -1721,7 +1721,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
{ {
struct m_can_classdev *cdev = netdev_priv(dev); struct m_can_classdev *cdev = netdev_priv(dev);
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (cdev->is_peripheral) { if (cdev->is_peripheral) {
......
...@@ -191,7 +191,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -191,7 +191,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
int i, rtr, buf_id; int i, rtr, buf_id;
u32 can_id; u32 can_id;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
out_8(&regs->cantier, 0); out_8(&regs->cantier, 0);
......
...@@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
int i; int i;
u32 id2; u32 id2;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_obj_no = priv->tx_obj; tx_obj_no = priv->tx_obj;
......
...@@ -651,7 +651,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb, ...@@ -651,7 +651,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
int room_left; int room_left;
u8 len; u8 len;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
msg_size = ALIGN(sizeof(*msg) + cf->len, 4); msg_size = ALIGN(sizeof(*msg) + cf->len, 4);
......
...@@ -590,7 +590,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb, ...@@ -590,7 +590,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
struct can_frame *cf = (struct can_frame *)skb->data; struct can_frame *cf = (struct can_frame *)skb->data;
u32 data, i; u32 data, i;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */ if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
......
...@@ -1481,7 +1481,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, ...@@ -1481,7 +1481,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
unsigned long flags; unsigned long flags;
u32 ch = priv->channel; u32 ch = priv->channel;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (cf->can_id & CAN_EFF_FLAG) { if (cf->can_id & CAN_EFF_FLAG) {
......
...@@ -291,7 +291,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb, ...@@ -291,7 +291,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
u8 cmd_reg_val = 0x00; u8 cmd_reg_val = 0x00;
int i; int i;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); netif_stop_queue(dev);
......
...@@ -594,7 +594,7 @@ static netdev_tx_t slcan_netdev_xmit(struct sk_buff *skb, ...@@ -594,7 +594,7 @@ static netdev_tx_t slcan_netdev_xmit(struct sk_buff *skb,
{ {
struct slcan *sl = netdev_priv(dev); struct slcan *sl = netdev_priv(dev);
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock(&sl->lock); spin_lock(&sl->lock);
......
...@@ -60,7 +60,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb, ...@@ -60,7 +60,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
struct can_frame *cf = (struct can_frame *)skb->data; struct can_frame *cf = (struct can_frame *)skb->data;
uint8_t buf[DPRAM_TX_SIZE]; uint8_t buf[DPRAM_TX_SIZE];
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock(&card->spin); spin_lock(&card->spin);
......
...@@ -373,7 +373,7 @@ static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb, ...@@ -373,7 +373,7 @@ static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
if (can_dropped_invalid_skb(net, skb)) if (can_dev_dropped_skb(net, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(net); netif_stop_queue(net);
......
...@@ -789,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, ...@@ -789,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
if (can_dropped_invalid_skb(net, skb)) if (can_dev_dropped_skb(net, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(net); netif_stop_queue(net);
......
...@@ -172,7 +172,7 @@ netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, ...@@ -172,7 +172,7 @@ netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
u8 tx_head; u8 tx_head;
int err; int err;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (mcp251xfd_tx_busy(priv, tx_ring)) if (mcp251xfd_tx_busy(priv, tx_ring))
......
...@@ -429,7 +429,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d ...@@ -429,7 +429,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d
canid_t id; canid_t id;
int i; int i;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); netif_stop_queue(dev);
......
...@@ -470,7 +470,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -470,7 +470,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
u32 mbxno, mbx_mask, data; u32 mbxno, mbx_mask, data;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
mbxno = get_tx_head_mb(priv); mbxno = get_tx_head_mb(priv);
......
...@@ -747,7 +747,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne ...@@ -747,7 +747,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
+ sizeof(struct cpc_can_msg); + sizeof(struct cpc_can_msg);
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* create a URB, and a buffer for it, and copy the data to the URB */ /* create a URB, and a buffer for it, and copy the data to the URB */
......
...@@ -725,7 +725,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, ...@@ -725,7 +725,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
int ret = NETDEV_TX_OK; int ret = NETDEV_TX_OK;
size_t size = sizeof(struct esd_usb_msg); size_t size = sizeof(struct esd_usb_msg);
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* create a URB, and a buffer for it, and copy the data to the URB */ /* create a URB, and a buffer for it, and copy the data to the URB */
......
...@@ -1913,7 +1913,7 @@ static netdev_tx_t es58x_start_xmit(struct sk_buff *skb, ...@@ -1913,7 +1913,7 @@ static netdev_tx_t es58x_start_xmit(struct sk_buff *skb,
unsigned int frame_len; unsigned int frame_len;
int ret; int ret;
if (can_dropped_invalid_skb(netdev, skb)) { if (can_dev_dropped_skb(netdev, skb)) {
if (priv->tx_urb) if (priv->tx_urb)
goto xmit_commit; goto xmit_commit;
return NETDEV_TX_OK; return NETDEV_TX_OK;
......
...@@ -723,7 +723,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, ...@@ -723,7 +723,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
unsigned int idx; unsigned int idx;
struct gs_tx_context *txc; struct gs_tx_context *txc;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* find an empty context to keep track of transmission */ /* find an empty context to keep track of transmission */
......
...@@ -570,7 +570,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, ...@@ -570,7 +570,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
unsigned int i; unsigned int i;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
urb = usb_alloc_urb(0, GFP_ATOMIC); urb = usb_alloc_urb(0, GFP_ATOMIC);
......
...@@ -311,7 +311,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb, ...@@ -311,7 +311,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
.cmd_id = MBCA_CMD_TRANSMIT_MESSAGE_EV .cmd_id = MBCA_CMD_TRANSMIT_MESSAGE_EV
}; };
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
ctx = mcba_usb_get_free_ctx(priv, cf); ctx = mcba_usb_get_free_ctx(priv, cf);
......
...@@ -351,7 +351,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb, ...@@ -351,7 +351,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb,
int i, err; int i, err;
size_t size = dev->adapter->tx_buffer_size; size_t size = dev->adapter->tx_buffer_size;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++) for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++)
......
...@@ -1120,7 +1120,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb, ...@@ -1120,7 +1120,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
struct can_frame *cf = (struct can_frame *)skb->data; struct can_frame *cf = (struct can_frame *)skb->data;
/* check skb */ /* check skb */
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* allocate a context and slow down tx path, if fifo state is low */ /* allocate a context and slow down tx path, if fifo state is low */
......
...@@ -602,7 +602,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb, ...@@ -602,7 +602,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
int i, err; int i, err;
size_t size = sizeof(struct usb_8dev_tx_msg); size_t size = sizeof(struct usb_8dev_tx_msg);
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* create a URB, and a buffer for it, and copy the data to the URB */ /* create a URB, and a buffer for it, and copy the data to the URB */
......
...@@ -743,7 +743,7 @@ static netdev_tx_t xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -743,7 +743,7 @@ static netdev_tx_t xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev)
struct xcan_priv *priv = netdev_priv(ndev); struct xcan_priv *priv = netdev_priv(ndev);
int ret; int ret;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES)
......
...@@ -152,6 +152,22 @@ static inline bool can_is_canxl_dev_mtu(unsigned int mtu) ...@@ -152,6 +152,22 @@ static inline bool can_is_canxl_dev_mtu(unsigned int mtu)
return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU); return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU);
} }
/* drop skb if it does not contain a valid CAN frame for sending */
static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb)
{
struct can_priv *priv = netdev_priv(dev);
if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
netdev_info_once(dev,
"interface in listen only mode, dropping skb\n");
kfree_skb(skb);
dev->stats.tx_dropped++;
return true;
}
return can_dropped_invalid_skb(dev, skb);
}
void can_setup(struct net_device *dev); void can_setup(struct net_device *dev);
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册