File Index
Files and directories
Sign in
FILE

nf_conntrack_tftp.c

File preview with syntax highlighting.

linux-6.19.14/net/netfilter/nf_conntrack_tftp.c C
  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);
~/ Read-only file preview.