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

nf_conntrack_tftp.c (3854B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
      3 * (C) 2006-2012 Patrick McHardy <kaber@trash.net>
      4 */
      5
      6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      7
      8#include <linux/module.h>
      9#include <linux/moduleparam.h>
     10#include <linux/in.h>
     11#include <linux/udp.h>
     12#include <linux/netfilter.h>
     13
     14#include <net/netfilter/nf_conntrack.h>
     15#include <net/netfilter/nf_conntrack_tuple.h>
     16#include <net/netfilter/nf_conntrack_expect.h>
     17#include <net/netfilter/nf_conntrack_ecache.h>
     18#include <net/netfilter/nf_conntrack_helper.h>
     19#include <linux/netfilter/nf_conntrack_tftp.h>
     20
     21#define HELPER_NAME "tftp"
     22
     23MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
     24MODULE_DESCRIPTION("TFTP connection tracking helper");
     25MODULE_LICENSE("GPL");
     26MODULE_ALIAS("ip_conntrack_tftp");
     27MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
     28
     29#define MAX_PORTS 8
     30static unsigned short ports[MAX_PORTS];
     31static unsigned int ports_c;
     32module_param_array(ports, ushort, &ports_c, 0400);
     33MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
     34
     35unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
     36				 enum ip_conntrack_info ctinfo,
     37				 struct nf_conntrack_expect *exp) __read_mostly;
     38EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
     39
     40static int tftp_help(struct sk_buff *skb,
     41		     unsigned int protoff,
     42		     struct nf_conn *ct,
     43		     enum ip_conntrack_info ctinfo)
     44{
     45	const struct tftphdr *tfh;
     46	struct tftphdr _tftph;
     47	struct nf_conntrack_expect *exp;
     48	struct nf_conntrack_tuple *tuple;
     49	unsigned int ret = NF_ACCEPT;
     50	typeof(nf_nat_tftp_hook) nf_nat_tftp;
     51
     52	tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
     53				 sizeof(_tftph), &_tftph);
     54	if (tfh == NULL)
     55		return NF_ACCEPT;
     56
     57	switch (ntohs(tfh->opcode)) {
     58	case TFTP_OPCODE_READ:
     59	case TFTP_OPCODE_WRITE:
     60		/* RRQ and WRQ works the same way */
     61		nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
     62		nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
     63
     64		exp = nf_ct_expect_alloc(ct);
     65		if (exp == NULL) {
     66			nf_ct_helper_log(skb, ct, "cannot alloc expectation");
     67			return NF_DROP;
     68		}
     69		tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
     70		nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
     71				  nf_ct_l3num(ct),
     72				  &tuple->src.u3, &tuple->dst.u3,
     73				  IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
     74
     75		pr_debug("expect: ");
     76		nf_ct_dump_tuple(&exp->tuple);
     77
     78		nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
     79		if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
     80			ret = nf_nat_tftp(skb, ctinfo, exp);
     81		else if (nf_ct_expect_related(exp, 0) != 0) {
     82			nf_ct_helper_log(skb, ct, "cannot add expectation");
     83			ret = NF_DROP;
     84		}
     85		nf_ct_expect_put(exp);
     86		break;
     87	case TFTP_OPCODE_DATA:
     88	case TFTP_OPCODE_ACK:
     89		pr_debug("Data/ACK opcode\n");
     90		break;
     91	case TFTP_OPCODE_ERROR:
     92		pr_debug("Error opcode\n");
     93		break;
     94	default:
     95		pr_debug("Unknown opcode\n");
     96	}
     97	return ret;
     98}
     99
    100static struct nf_conntrack_helper tftp[MAX_PORTS * 2] __read_mostly;
    101
    102static const struct nf_conntrack_expect_policy tftp_exp_policy = {
    103	.max_expected	= 1,
    104	.timeout	= 5 * 60,
    105};
    106
    107static void __exit nf_conntrack_tftp_fini(void)
    108{
    109	nf_conntrack_helpers_unregister(tftp, ports_c * 2);
    110}
    111
    112static int __init nf_conntrack_tftp_init(void)
    113{
    114	int i, ret;
    115
    116	NF_CT_HELPER_BUILD_BUG_ON(0);
    117
    118	if (ports_c == 0)
    119		ports[ports_c++] = TFTP_PORT;
    120
    121	for (i = 0; i < ports_c; i++) {
    122		nf_ct_helper_init(&tftp[2 * i], AF_INET, IPPROTO_UDP,
    123				  HELPER_NAME, TFTP_PORT, ports[i], i,
    124				  &tftp_exp_policy, 0, tftp_help, NULL,
    125				  THIS_MODULE);
    126		nf_ct_helper_init(&tftp[2 * i + 1], AF_INET6, IPPROTO_UDP,
    127				  HELPER_NAME, TFTP_PORT, ports[i], i,
    128				  &tftp_exp_policy, 0, tftp_help, NULL,
    129				  THIS_MODULE);
    130	}
    131
    132	ret = nf_conntrack_helpers_register(tftp, ports_c * 2);
    133	if (ret < 0) {
    134		pr_err("failed to register helpers\n");
    135		return ret;
    136	}
    137	return 0;
    138}
    139
    140module_init(nf_conntrack_tftp_init);
    141module_exit(nf_conntrack_tftp_fini);