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

nft_byteorder.c (4729B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
      4 *
      5 * Development of this code funded by Astaro AG (http://www.astaro.com/)
      6 */
      7
      8#include <asm/unaligned.h>
      9#include <linux/kernel.h>
     10#include <linux/init.h>
     11#include <linux/module.h>
     12#include <linux/netlink.h>
     13#include <linux/netfilter.h>
     14#include <linux/netfilter/nf_tables.h>
     15#include <net/netfilter/nf_tables_core.h>
     16#include <net/netfilter/nf_tables.h>
     17
     18struct nft_byteorder {
     19	u8			sreg;
     20	u8			dreg;
     21	enum nft_byteorder_ops	op:8;
     22	u8			len;
     23	u8			size;
     24};
     25
     26void nft_byteorder_eval(const struct nft_expr *expr,
     27			struct nft_regs *regs,
     28			const struct nft_pktinfo *pkt)
     29{
     30	const struct nft_byteorder *priv = nft_expr_priv(expr);
     31	u32 *src = &regs->data[priv->sreg];
     32	u32 *dst = &regs->data[priv->dreg];
     33	union { u32 u32; u16 u16; } *s, *d;
     34	unsigned int i;
     35
     36	s = (void *)src;
     37	d = (void *)dst;
     38
     39	switch (priv->size) {
     40	case 8: {
     41		u64 src64;
     42
     43		switch (priv->op) {
     44		case NFT_BYTEORDER_NTOH:
     45			for (i = 0; i < priv->len / 8; i++) {
     46				src64 = nft_reg_load64(&src[i]);
     47				nft_reg_store64(&dst[i], be64_to_cpu(src64));
     48			}
     49			break;
     50		case NFT_BYTEORDER_HTON:
     51			for (i = 0; i < priv->len / 8; i++) {
     52				src64 = (__force __u64)
     53					cpu_to_be64(nft_reg_load64(&src[i]));
     54				nft_reg_store64(&dst[i], src64);
     55			}
     56			break;
     57		}
     58		break;
     59	}
     60	case 4:
     61		switch (priv->op) {
     62		case NFT_BYTEORDER_NTOH:
     63			for (i = 0; i < priv->len / 4; i++)
     64				d[i].u32 = ntohl((__force __be32)s[i].u32);
     65			break;
     66		case NFT_BYTEORDER_HTON:
     67			for (i = 0; i < priv->len / 4; i++)
     68				d[i].u32 = (__force __u32)htonl(s[i].u32);
     69			break;
     70		}
     71		break;
     72	case 2:
     73		switch (priv->op) {
     74		case NFT_BYTEORDER_NTOH:
     75			for (i = 0; i < priv->len / 2; i++)
     76				d[i].u16 = ntohs((__force __be16)s[i].u16);
     77			break;
     78		case NFT_BYTEORDER_HTON:
     79			for (i = 0; i < priv->len / 2; i++)
     80				d[i].u16 = (__force __u16)htons(s[i].u16);
     81			break;
     82		}
     83		break;
     84	}
     85}
     86
     87static const struct nla_policy nft_byteorder_policy[NFTA_BYTEORDER_MAX + 1] = {
     88	[NFTA_BYTEORDER_SREG]	= { .type = NLA_U32 },
     89	[NFTA_BYTEORDER_DREG]	= { .type = NLA_U32 },
     90	[NFTA_BYTEORDER_OP]	= { .type = NLA_U32 },
     91	[NFTA_BYTEORDER_LEN]	= { .type = NLA_U32 },
     92	[NFTA_BYTEORDER_SIZE]	= { .type = NLA_U32 },
     93};
     94
     95static int nft_byteorder_init(const struct nft_ctx *ctx,
     96			      const struct nft_expr *expr,
     97			      const struct nlattr * const tb[])
     98{
     99	struct nft_byteorder *priv = nft_expr_priv(expr);
    100	u32 size, len;
    101	int err;
    102
    103	if (tb[NFTA_BYTEORDER_SREG] == NULL ||
    104	    tb[NFTA_BYTEORDER_DREG] == NULL ||
    105	    tb[NFTA_BYTEORDER_LEN] == NULL ||
    106	    tb[NFTA_BYTEORDER_SIZE] == NULL ||
    107	    tb[NFTA_BYTEORDER_OP] == NULL)
    108		return -EINVAL;
    109
    110	priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP]));
    111	switch (priv->op) {
    112	case NFT_BYTEORDER_NTOH:
    113	case NFT_BYTEORDER_HTON:
    114		break;
    115	default:
    116		return -EINVAL;
    117	}
    118
    119	err = nft_parse_u32_check(tb[NFTA_BYTEORDER_SIZE], U8_MAX, &size);
    120	if (err < 0)
    121		return err;
    122
    123	priv->size = size;
    124
    125	switch (priv->size) {
    126	case 2:
    127	case 4:
    128	case 8:
    129		break;
    130	default:
    131		return -EINVAL;
    132	}
    133
    134	err = nft_parse_u32_check(tb[NFTA_BYTEORDER_LEN], U8_MAX, &len);
    135	if (err < 0)
    136		return err;
    137
    138	priv->len = len;
    139
    140	err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg,
    141				      priv->len);
    142	if (err < 0)
    143		return err;
    144
    145	return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
    146					&priv->dreg, NULL, NFT_DATA_VALUE,
    147					priv->len);
    148}
    149
    150static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr)
    151{
    152	const struct nft_byteorder *priv = nft_expr_priv(expr);
    153
    154	if (nft_dump_register(skb, NFTA_BYTEORDER_SREG, priv->sreg))
    155		goto nla_put_failure;
    156	if (nft_dump_register(skb, NFTA_BYTEORDER_DREG, priv->dreg))
    157		goto nla_put_failure;
    158	if (nla_put_be32(skb, NFTA_BYTEORDER_OP, htonl(priv->op)))
    159		goto nla_put_failure;
    160	if (nla_put_be32(skb, NFTA_BYTEORDER_LEN, htonl(priv->len)))
    161		goto nla_put_failure;
    162	if (nla_put_be32(skb, NFTA_BYTEORDER_SIZE, htonl(priv->size)))
    163		goto nla_put_failure;
    164	return 0;
    165
    166nla_put_failure:
    167	return -1;
    168}
    169
    170static bool nft_byteorder_reduce(struct nft_regs_track *track,
    171				 const struct nft_expr *expr)
    172{
    173	struct nft_byteorder *priv = nft_expr_priv(expr);
    174
    175	nft_reg_track_cancel(track, priv->dreg, priv->len);
    176
    177	return false;
    178}
    179
    180static const struct nft_expr_ops nft_byteorder_ops = {
    181	.type		= &nft_byteorder_type,
    182	.size		= NFT_EXPR_SIZE(sizeof(struct nft_byteorder)),
    183	.eval		= nft_byteorder_eval,
    184	.init		= nft_byteorder_init,
    185	.dump		= nft_byteorder_dump,
    186	.reduce		= nft_byteorder_reduce,
    187};
    188
    189struct nft_expr_type nft_byteorder_type __read_mostly = {
    190	.name		= "byteorder",
    191	.ops		= &nft_byteorder_ops,
    192	.policy		= nft_byteorder_policy,
    193	.maxattr	= NFTA_BYTEORDER_MAX,
    194	.owner		= THIS_MODULE,
    195};