1 /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ 2 /* 3 * linux/can/skb.h 4 * 5 * Definitions for the CAN network socket buffer 6 * 7 * Copyright (C) 2012 Oliver Hartkopp <[email protected]> 8 * 9 */ 10 11 #ifndef _CAN_SKB_H 12 #define _CAN_SKB_H 13 14 #include <linux/types.h> 15 #include <linux/skbuff.h> 16 #include <linux/can.h> 17 #include <net/sock.h> 18 19 void can_flush_echo_skb(struct net_device *dev); 20 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, 21 unsigned int idx, unsigned int frame_len); 22 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, 23 u8 *len_ptr, unsigned int *frame_len_ptr); 24 unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx, 25 unsigned int *frame_len_ptr); 26 void can_free_echo_skb(struct net_device *dev, unsigned int idx); 27 struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf); 28 struct sk_buff *alloc_canfd_skb(struct net_device *dev, 29 struct canfd_frame **cfd); 30 struct sk_buff *alloc_can_err_skb(struct net_device *dev, 31 struct can_frame **cf); 32 33 /* 34 * The struct can_skb_priv is used to transport additional information along 35 * with the stored struct can(fd)_frame that can not be contained in existing 36 * struct sk_buff elements. 37 * N.B. that this information must not be modified in cloned CAN sk_buffs. 38 * To modify the CAN frame content or the struct can_skb_priv content 39 * skb_copy() needs to be used instead of skb_clone(). 40 */ 41 42 /** 43 * struct can_skb_priv - private additional data inside CAN sk_buffs 44 * @ifindex: ifindex of the first interface the CAN frame appeared on 45 * @skbcnt: atomic counter to have an unique id together with skb pointer 46 * @frame_len: length of CAN frame in data link layer 47 * @cf: align to the following CAN frame at skb->data 48 */ 49 struct can_skb_priv { 50 int ifindex; 51 int skbcnt; 52 unsigned int frame_len; 53 struct can_frame cf[]; 54 }; 55 56 static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb) 57 { 58 return (struct can_skb_priv *)(skb->head); 59 } 60 61 static inline void can_skb_reserve(struct sk_buff *skb) 62 { 63 skb_reserve(skb, sizeof(struct can_skb_priv)); 64 } 65 66 static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) 67 { 68 if (sk) { 69 sock_hold(sk); 70 skb->destructor = sock_efree; 71 skb->sk = sk; 72 } 73 } 74 75 /* 76 * returns an unshared skb owned by the original sock to be echo'ed back 77 */ 78 static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) 79 { 80 struct sk_buff *nskb; 81 82 nskb = skb_clone(skb, GFP_ATOMIC); 83 if (unlikely(!nskb)) { 84 kfree_skb(skb); 85 return NULL; 86 } 87 88 can_skb_set_owner(nskb, skb->sk); 89 consume_skb(skb); 90 return nskb; 91 } 92 93 /* Check for outgoing skbs that have not been created by the CAN subsystem */ 94 static inline bool can_skb_headroom_valid(struct net_device *dev, 95 struct sk_buff *skb) 96 { 97 /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */ 98 if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv))) 99 return false; 100 101 /* af_packet does not apply CAN skb specific settings */ 102 if (skb->ip_summed == CHECKSUM_NONE) { 103 /* init headroom */ 104 can_skb_prv(skb)->ifindex = dev->ifindex; 105 can_skb_prv(skb)->skbcnt = 0; 106 107 skb->ip_summed = CHECKSUM_UNNECESSARY; 108 109 /* perform proper loopback on capable devices */ 110 if (dev->flags & IFF_ECHO) 111 skb->pkt_type = PACKET_LOOPBACK; 112 else 113 skb->pkt_type = PACKET_HOST; 114 115 skb_reset_mac_header(skb); 116 skb_reset_network_header(skb); 117 skb_reset_transport_header(skb); 118 } 119 120 return true; 121 } 122 123 /* Drop a given socketbuffer if it does not contain a valid CAN frame. */ 124 static inline bool can_dropped_invalid_skb(struct net_device *dev, 125 struct sk_buff *skb) 126 { 127 const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 128 129 if (skb->protocol == htons(ETH_P_CAN)) { 130 if (unlikely(skb->len != CAN_MTU || 131 cfd->len > CAN_MAX_DLEN)) 132 goto inval_skb; 133 } else if (skb->protocol == htons(ETH_P_CANFD)) { 134 if (unlikely(skb->len != CANFD_MTU || 135 cfd->len > CANFD_MAX_DLEN)) 136 goto inval_skb; 137 } else 138 goto inval_skb; 139 140 if (!can_skb_headroom_valid(dev, skb)) 141 goto inval_skb; 142 143 return false; 144 145 inval_skb: 146 kfree_skb(skb); 147 dev->stats.tx_dropped++; 148 return true; 149 } 150 151 static inline bool can_is_canfd_skb(const struct sk_buff *skb) 152 { 153 /* the CAN specific type of skb is identified by its data length */ 154 return skb->len == CANFD_MTU; 155 } 156 157 #endif /* !_CAN_SKB_H */ 158