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

em_ipset.c (3020B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * net/sched/em_ipset.c	ipset ematch
      4 *
      5 * Copyright (c) 2012 Florian Westphal <fw@strlen.de>
      6 */
      7
      8#include <linux/gfp.h>
      9#include <linux/module.h>
     10#include <linux/types.h>
     11#include <linux/kernel.h>
     12#include <linux/string.h>
     13#include <linux/skbuff.h>
     14#include <linux/netfilter/xt_set.h>
     15#include <linux/ipv6.h>
     16#include <net/ip.h>
     17#include <net/pkt_cls.h>
     18
     19static int em_ipset_change(struct net *net, void *data, int data_len,
     20			   struct tcf_ematch *em)
     21{
     22	struct xt_set_info *set = data;
     23	ip_set_id_t index;
     24
     25	if (data_len != sizeof(*set))
     26		return -EINVAL;
     27
     28	index = ip_set_nfnl_get_byindex(net, set->index);
     29	if (index == IPSET_INVALID_ID)
     30		return -ENOENT;
     31
     32	em->datalen = sizeof(*set);
     33	em->data = (unsigned long)kmemdup(data, em->datalen, GFP_KERNEL);
     34	if (em->data)
     35		return 0;
     36
     37	ip_set_nfnl_put(net, index);
     38	return -ENOMEM;
     39}
     40
     41static void em_ipset_destroy(struct tcf_ematch *em)
     42{
     43	const struct xt_set_info *set = (const void *) em->data;
     44	if (set) {
     45		ip_set_nfnl_put(em->net, set->index);
     46		kfree((void *) em->data);
     47	}
     48}
     49
     50static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
     51			  struct tcf_pkt_info *info)
     52{
     53	struct ip_set_adt_opt opt;
     54	struct xt_action_param acpar;
     55	const struct xt_set_info *set = (const void *) em->data;
     56	struct net_device *dev, *indev = NULL;
     57	struct nf_hook_state state = {
     58		.net	= em->net,
     59	};
     60	int ret, network_offset;
     61
     62	switch (skb_protocol(skb, true)) {
     63	case htons(ETH_P_IP):
     64		state.pf = NFPROTO_IPV4;
     65		if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
     66			return 0;
     67		acpar.thoff = ip_hdrlen(skb);
     68		break;
     69	case htons(ETH_P_IPV6):
     70		state.pf = NFPROTO_IPV6;
     71		if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
     72			return 0;
     73		/* doesn't call ipv6_find_hdr() because ipset doesn't use thoff, yet */
     74		acpar.thoff = sizeof(struct ipv6hdr);
     75		break;
     76	default:
     77		return 0;
     78	}
     79
     80	opt.family = state.pf;
     81	opt.dim = set->dim;
     82	opt.flags = set->flags;
     83	opt.cmdflags = 0;
     84	opt.ext.timeout = ~0u;
     85
     86	network_offset = skb_network_offset(skb);
     87	skb_pull(skb, network_offset);
     88
     89	dev = skb->dev;
     90
     91	rcu_read_lock();
     92
     93	if (skb->skb_iif)
     94		indev = dev_get_by_index_rcu(em->net, skb->skb_iif);
     95
     96	state.in      = indev ? indev : dev;
     97	state.out     = dev;
     98	acpar.state   = &state;
     99
    100	ret = ip_set_test(set->index, skb, &acpar, &opt);
    101
    102	rcu_read_unlock();
    103
    104	skb_push(skb, network_offset);
    105	return ret;
    106}
    107
    108static struct tcf_ematch_ops em_ipset_ops = {
    109	.kind	  = TCF_EM_IPSET,
    110	.change	  = em_ipset_change,
    111	.destroy  = em_ipset_destroy,
    112	.match	  = em_ipset_match,
    113	.owner	  = THIS_MODULE,
    114	.link	  = LIST_HEAD_INIT(em_ipset_ops.link)
    115};
    116
    117static int __init init_em_ipset(void)
    118{
    119	return tcf_em_register(&em_ipset_ops);
    120}
    121
    122static void __exit exit_em_ipset(void)
    123{
    124	tcf_em_unregister(&em_ipset_ops);
    125}
    126
    127MODULE_LICENSE("GPL");
    128MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
    129MODULE_DESCRIPTION("TC extended match for IP sets");
    130
    131module_init(init_em_ipset);
    132module_exit(exit_em_ipset);
    133
    134MODULE_ALIAS_TCF_EMATCH(TCF_EM_IPSET);