cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

skb.h (4655B)


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