#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/can.h>
+#include <linux/can/can-ml.h>
#include <linux/can/core.h>
-#include <linux/can/dev.h> /* for can_is_canxl_dev_mtu() */
#include <linux/can/skb.h>
#include <linux/can/raw.h>
#include <net/sock.h>
}
}
-static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu)
+static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb,
+ struct net_device *dev)
{
- /* Classical CAN -> no checks for flags and device capabilities */
- if (can_is_can_skb(skb))
+ /* Classical CAN */
+ if (can_is_can_skb(skb) && can_cap_enabled(dev, CAN_CAP_CC))
return CAN_MTU;
- /* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */
+ /* CAN FD */
if (ro->fd_frames && can_is_canfd_skb(skb) &&
- (mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu)))
+ can_cap_enabled(dev, CAN_CAP_FD))
return CANFD_MTU;
- /* CAN XL -> needs to be enabled and a CAN XL device */
+ /* CAN XL */
if (ro->xl_frames && can_is_canxl_skb(skb) &&
- can_is_canxl_dev_mtu(mtu))
+ can_cap_enabled(dev, CAN_CAP_XL))
return CANXL_MTU;
return 0;
if (!dev)
return -ENXIO;
+ /* no sending on a CAN device in read-only mode */
+ if (can_cap_enabled(dev, CAN_CAP_RO)) {
+ err = -EACCES;
+ goto put_dev;
+ }
+
skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
err = -EINVAL;
/* check for valid CAN (CC/FD/XL) frame content */
- txmtu = raw_check_txframe(ro, skb, READ_ONCE(dev->mtu));
+ txmtu = raw_check_txframe(ro, skb, dev);
if (!txmtu)
goto free_skb;