Commit 1afc5679 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_ct_helper: implement variable length helper private data

This patch uses the new variable length conntrack extensions.

Instead of using union nf_conntrack_help that contain all the
helper private data information, we allocate variable length
area to store the private helper data.

This patch includes the modification of all existing helpers.
It also includes a couple of include header to avoid compilation
warnings.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 3cf4c7e3
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#define __NF_CONNTRACK_SIP_H__ #define __NF_CONNTRACK_SIP_H__
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <net/netfilter/nf_conntrack_expect.h>
#define SIP_PORT 5060 #define SIP_PORT 5060
#define SIP_TIMEOUT 3600 #define SIP_TIMEOUT 3600
......
...@@ -39,36 +39,6 @@ union nf_conntrack_expect_proto { ...@@ -39,36 +39,6 @@ union nf_conntrack_expect_proto {
/* insert expect proto private data here */ /* insert expect proto private data here */
}; };
/* Add protocol helper include file here */
#include <linux/netfilter/nf_conntrack_ftp.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <linux/netfilter/nf_conntrack_h323.h>
#include <linux/netfilter/nf_conntrack_sane.h>
#include <linux/netfilter/nf_conntrack_sip.h>
/* per conntrack: application helper private data */
union nf_conntrack_help {
/* insert conntrack helper private data (master) here */
#if defined(CONFIG_NF_CONNTRACK_FTP) || defined(CONFIG_NF_CONNTRACK_FTP_MODULE)
struct nf_ct_ftp_master ct_ftp_info;
#endif
#if defined(CONFIG_NF_CONNTRACK_PPTP) || \
defined(CONFIG_NF_CONNTRACK_PPTP_MODULE)
struct nf_ct_pptp_master ct_pptp_info;
#endif
#if defined(CONFIG_NF_CONNTRACK_H323) || \
defined(CONFIG_NF_CONNTRACK_H323_MODULE)
struct nf_ct_h323_master ct_h323_info;
#endif
#if defined(CONFIG_NF_CONNTRACK_SANE) || \
defined(CONFIG_NF_CONNTRACK_SANE_MODULE)
struct nf_ct_sane_master ct_sane_info;
#endif
#if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
struct nf_ct_sip_master ct_sip_info;
#endif
};
#include <linux/types.h> #include <linux/types.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -89,12 +59,13 @@ struct nf_conn_help { ...@@ -89,12 +59,13 @@ struct nf_conn_help {
/* Helper. if any */ /* Helper. if any */
struct nf_conntrack_helper __rcu *helper; struct nf_conntrack_helper __rcu *helper;
union nf_conntrack_help help;
struct hlist_head expectations; struct hlist_head expectations;
/* Current number of expected connections */ /* Current number of expected connections */
u8 expecting[NF_CT_MAX_EXPECT_CLASSES]; u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
/* private helper information. */
char data[];
}; };
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define _NF_CONNTRACK_HELPER_H #define _NF_CONNTRACK_HELPER_H
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h> #include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_expect.h>
struct module; struct module;
...@@ -23,6 +24,9 @@ struct nf_conntrack_helper { ...@@ -23,6 +24,9 @@ struct nf_conntrack_helper {
struct module *me; /* pointer to self */ struct module *me; /* pointer to self */
const struct nf_conntrack_expect_policy *expect_policy; const struct nf_conntrack_expect_policy *expect_policy;
/* length of internal data, ie. sizeof(struct nf_ct_*_master) */
size_t data_len;
/* Tuple of things we will help (compared against server response) */ /* Tuple of things we will help (compared against server response) */
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
...@@ -48,7 +52,7 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum); ...@@ -48,7 +52,7 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, struct nf_conntrack_helper *helper, gfp_t gfp);
extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
gfp_t flags); gfp_t flags);
...@@ -60,6 +64,15 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) ...@@ -60,6 +64,15 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
} }
static inline void *nfct_help_data(const struct nf_conn *ct)
{
struct nf_conn_help *help;
help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
return (void *)help->data;
}
extern int nf_conntrack_helper_init(struct net *net); extern int nf_conntrack_helper_init(struct net *net);
extern void nf_conntrack_helper_fini(struct net *net); extern void nf_conntrack_helper_fini(struct net *net);
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/udp.h> #include <linux/udp.h>
#include <net/netfilter/nf_nat_helper.h>
#include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_nat_helper.h>
#include <net/netfilter/nf_nat_rule.h>
#include <linux/netfilter/nf_conntrack_amanda.h> #include <linux/netfilter/nf_conntrack_amanda.h>
MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
......
...@@ -95,7 +95,7 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, ...@@ -95,7 +95,7 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
unsigned char **data, unsigned char **data,
TransportAddress *taddr, int count) TransportAddress *taddr, int count)
{ {
const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; const struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
int i; int i;
__be16 port; __be16 port;
...@@ -178,7 +178,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, ...@@ -178,7 +178,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
struct nf_conntrack_expect *rtp_exp, struct nf_conntrack_expect *rtp_exp,
struct nf_conntrack_expect *rtcp_exp) struct nf_conntrack_expect *rtcp_exp)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
int i; int i;
u_int16_t nated_port; u_int16_t nated_port;
...@@ -330,7 +330,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, ...@@ -330,7 +330,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
TransportAddress *taddr, __be16 port, TransportAddress *taddr, __be16 port,
struct nf_conntrack_expect *exp) struct nf_conntrack_expect *exp)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
u_int16_t nated_port = ntohs(port); u_int16_t nated_port = ntohs(port);
...@@ -419,7 +419,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, ...@@ -419,7 +419,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
unsigned char **data, TransportAddress *taddr, int idx, unsigned char **data, TransportAddress *taddr, int idx,
__be16 port, struct nf_conntrack_expect *exp) __be16 port, struct nf_conntrack_expect *exp)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
u_int16_t nated_port = ntohs(port); u_int16_t nated_port = ntohs(port);
union nf_inet_addr addr; union nf_inet_addr addr;
......
...@@ -49,7 +49,7 @@ static void pptp_nat_expected(struct nf_conn *ct, ...@@ -49,7 +49,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
const struct nf_nat_pptp *nat_pptp_info; const struct nf_nat_pptp *nat_pptp_info;
struct nf_nat_ipv4_range range; struct nf_nat_ipv4_range range;
ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; ct_pptp_info = nfct_help_data(master);
nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
/* And here goes the grand finale of corrosion... */ /* And here goes the grand finale of corrosion... */
...@@ -123,7 +123,7 @@ pptp_outbound_pkt(struct sk_buff *skb, ...@@ -123,7 +123,7 @@ pptp_outbound_pkt(struct sk_buff *skb,
__be16 new_callid; __be16 new_callid;
unsigned int cid_off; unsigned int cid_off;
ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info; ct_pptp_info = nfct_help_data(ct);
nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info; nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
new_callid = ct_pptp_info->pns_call_id; new_callid = ct_pptp_info->pns_call_id;
...@@ -192,7 +192,7 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig, ...@@ -192,7 +192,7 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
struct nf_ct_pptp_master *ct_pptp_info; struct nf_ct_pptp_master *ct_pptp_info;
struct nf_nat_pptp *nat_pptp_info; struct nf_nat_pptp *nat_pptp_info;
ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info; ct_pptp_info = nfct_help_data(ct);
nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info; nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
/* save original PAC call ID in nat_info */ /* save original PAC call ID in nat_info */
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/udp.h> #include <linux/udp.h>
#include <net/netfilter/nf_nat_helper.h>
#include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_nat_helper.h>
#include <net/netfilter/nf_nat_rule.h>
#include <linux/netfilter/nf_conntrack_tftp.h> #include <linux/netfilter/nf_conntrack_tftp.h>
MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
......
...@@ -819,7 +819,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, ...@@ -819,7 +819,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
__set_bit(IPS_EXPECTED_BIT, &ct->status); __set_bit(IPS_EXPECTED_BIT, &ct->status);
ct->master = exp->master; ct->master = exp->master;
if (exp->helper) { if (exp->helper) {
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); help = nf_ct_helper_ext_add(ct, exp->helper,
GFP_ATOMIC);
if (help) if (help)
rcu_assign_pointer(help->helper, exp->helper); rcu_assign_pointer(help->helper, exp->helper);
} }
......
...@@ -358,7 +358,7 @@ static int help(struct sk_buff *skb, ...@@ -358,7 +358,7 @@ static int help(struct sk_buff *skb,
u32 seq; u32 seq;
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
unsigned int uninitialized_var(matchlen), uninitialized_var(matchoff); unsigned int uninitialized_var(matchlen), uninitialized_var(matchoff);
struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; struct nf_ct_ftp_master *ct_ftp_info = nfct_help_data(ct);
struct nf_conntrack_expect *exp; struct nf_conntrack_expect *exp;
union nf_inet_addr *daddr; union nf_inet_addr *daddr;
struct nf_conntrack_man cmd = {}; struct nf_conntrack_man cmd = {};
...@@ -554,6 +554,7 @@ static int __init nf_conntrack_ftp_init(void) ...@@ -554,6 +554,7 @@ static int __init nf_conntrack_ftp_init(void)
ftp[i][0].tuple.src.l3num = PF_INET; ftp[i][0].tuple.src.l3num = PF_INET;
ftp[i][1].tuple.src.l3num = PF_INET6; ftp[i][1].tuple.src.l3num = PF_INET6;
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
ftp[i][j].data_len = sizeof(struct nf_ct_ftp_master);
ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]); ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
ftp[i][j].tuple.dst.protonum = IPPROTO_TCP; ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
ftp[i][j].expect_policy = &ftp_exp_policy; ftp[i][j].expect_policy = &ftp_exp_policy;
......
...@@ -114,7 +114,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff, ...@@ -114,7 +114,7 @@ static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo, struct nf_conn *ct, enum ip_conntrack_info ctinfo,
unsigned char **data, int *datalen, int *dataoff) unsigned char **data, int *datalen, int *dataoff)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
const struct tcphdr *th; const struct tcphdr *th;
struct tcphdr _tcph; struct tcphdr _tcph;
...@@ -618,6 +618,7 @@ static const struct nf_conntrack_expect_policy h245_exp_policy = { ...@@ -618,6 +618,7 @@ static const struct nf_conntrack_expect_policy h245_exp_policy = {
static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = { static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
.name = "H.245", .name = "H.245",
.me = THIS_MODULE, .me = THIS_MODULE,
.data_len = sizeof(struct nf_ct_h323_master),
.tuple.src.l3num = AF_UNSPEC, .tuple.src.l3num = AF_UNSPEC,
.tuple.dst.protonum = IPPROTO_UDP, .tuple.dst.protonum = IPPROTO_UDP,
.help = h245_help, .help = h245_help,
...@@ -1170,6 +1171,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { ...@@ -1170,6 +1171,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
{ {
.name = "Q.931", .name = "Q.931",
.me = THIS_MODULE, .me = THIS_MODULE,
.data_len = sizeof(struct nf_ct_h323_master),
.tuple.src.l3num = AF_INET, .tuple.src.l3num = AF_INET,
.tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT), .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT),
.tuple.dst.protonum = IPPROTO_TCP, .tuple.dst.protonum = IPPROTO_TCP,
...@@ -1245,7 +1247,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, ...@@ -1245,7 +1247,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
unsigned char **data, unsigned char **data,
TransportAddress *taddr, int count) TransportAddress *taddr, int count)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
int ret = 0; int ret = 0;
int i; int i;
...@@ -1360,7 +1362,7 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, ...@@ -1360,7 +1362,7 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
unsigned char **data, RegistrationRequest *rrq) unsigned char **data, RegistrationRequest *rrq)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int ret; int ret;
typeof(set_ras_addr_hook) set_ras_addr; typeof(set_ras_addr_hook) set_ras_addr;
...@@ -1395,7 +1397,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, ...@@ -1395,7 +1397,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
unsigned char **data, RegistrationConfirm *rcf) unsigned char **data, RegistrationConfirm *rcf)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
int ret; int ret;
struct nf_conntrack_expect *exp; struct nf_conntrack_expect *exp;
...@@ -1444,7 +1446,7 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct, ...@@ -1444,7 +1446,7 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
unsigned char **data, UnregistrationRequest *urq) unsigned char **data, UnregistrationRequest *urq)
{ {
struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
int ret; int ret;
typeof(set_sig_addr_hook) set_sig_addr; typeof(set_sig_addr_hook) set_sig_addr;
...@@ -1476,7 +1478,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct, ...@@ -1476,7 +1478,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
unsigned char **data, AdmissionRequest *arq) unsigned char **data, AdmissionRequest *arq)
{ {
const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; const struct nf_ct_h323_master *info = nfct_help_data(ct);
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
__be16 port; __be16 port;
union nf_inet_addr addr; union nf_inet_addr addr;
...@@ -1743,6 +1745,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { ...@@ -1743,6 +1745,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
{ {
.name = "RAS", .name = "RAS",
.me = THIS_MODULE, .me = THIS_MODULE,
.data_len = sizeof(struct nf_ct_h323_master),
.tuple.src.l3num = AF_INET, .tuple.src.l3num = AF_INET,
.tuple.src.u.udp.port = cpu_to_be16(RAS_PORT), .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT),
.tuple.dst.protonum = IPPROTO_UDP, .tuple.dst.protonum = IPPROTO_UDP,
...@@ -1752,6 +1755,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { ...@@ -1752,6 +1755,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
{ {
.name = "RAS", .name = "RAS",
.me = THIS_MODULE, .me = THIS_MODULE,
.data_len = sizeof(struct nf_ct_h323_master),
.tuple.src.l3num = AF_INET6, .tuple.src.l3num = AF_INET6,
.tuple.src.u.udp.port = cpu_to_be16(RAS_PORT), .tuple.src.u.udp.port = cpu_to_be16(RAS_PORT),
.tuple.dst.protonum = IPPROTO_UDP, .tuple.dst.protonum = IPPROTO_UDP,
......
...@@ -161,11 +161,14 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum) ...@@ -161,11 +161,14 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
} }
EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) struct nf_conn_help *
nf_ct_helper_ext_add(struct nf_conn *ct,
struct nf_conntrack_helper *helper, gfp_t gfp)
{ {
struct nf_conn_help *help; struct nf_conn_help *help;
help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp); help = nf_ct_ext_add_length(ct, NF_CT_EXT_HELPER,
helper->data_len, gfp);
if (help) if (help)
INIT_HLIST_HEAD(&help->expectations); INIT_HLIST_HEAD(&help->expectations);
else else
...@@ -218,13 +221,13 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, ...@@ -218,13 +221,13 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
} }
if (help == NULL) { if (help == NULL) {
help = nf_ct_helper_ext_add(ct, flags); help = nf_ct_helper_ext_add(ct, helper, flags);
if (help == NULL) { if (help == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
} else { } else {
memset(&help->help, 0, sizeof(help->help)); memset(help->data, 0, helper->data_len);
} }
rcu_assign_pointer(help->helper, helper); rcu_assign_pointer(help->helper, helper);
......
...@@ -1218,7 +1218,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) ...@@ -1218,7 +1218,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
if (help->helper) if (help->helper)
return -EBUSY; return -EBUSY;
/* need to zero data of old helper */ /* need to zero data of old helper */
memset(&help->help, 0, sizeof(help->help)); memset(help->data, 0, help->helper->data_len);
} else { } else {
/* we cannot set a helper for an existing conntrack */ /* we cannot set a helper for an existing conntrack */
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -1440,7 +1440,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, ...@@ -1440,7 +1440,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
} else { } else {
struct nf_conn_help *help; struct nf_conn_help *help;
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); help = nf_ct_helper_ext_add(ct, helper, GFP_ATOMIC);
if (help == NULL) { if (help == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto err2; goto err2;
......
...@@ -174,7 +174,7 @@ static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct, ...@@ -174,7 +174,7 @@ static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct,
static void pptp_destroy_siblings(struct nf_conn *ct) static void pptp_destroy_siblings(struct nf_conn *ct)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
const struct nf_conn_help *help = nfct_help(ct); const struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
struct nf_conntrack_tuple t; struct nf_conntrack_tuple t;
nf_ct_gre_keymap_destroy(ct); nf_ct_gre_keymap_destroy(ct);
...@@ -182,16 +182,16 @@ static void pptp_destroy_siblings(struct nf_conn *ct) ...@@ -182,16 +182,16 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
/* try original (pns->pac) tuple */ /* try original (pns->pac) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t)); memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
t.dst.protonum = IPPROTO_GRE; t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; t.src.u.gre.key = ct_pptp_info->pns_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; t.dst.u.gre.key = ct_pptp_info->pac_call_id;
if (!destroy_sibling_or_exp(net, ct, &t)) if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout original pns->pac ct/exp\n"); pr_debug("failed to timeout original pns->pac ct/exp\n");
/* try reply (pac->pns) tuple */ /* try reply (pac->pns) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
t.dst.protonum = IPPROTO_GRE; t.dst.protonum = IPPROTO_GRE;
t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; t.src.u.gre.key = ct_pptp_info->pac_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; t.dst.u.gre.key = ct_pptp_info->pns_call_id;
if (!destroy_sibling_or_exp(net, ct, &t)) if (!destroy_sibling_or_exp(net, ct, &t))
pr_debug("failed to timeout reply pac->pns ct/exp\n"); pr_debug("failed to timeout reply pac->pns ct/exp\n");
} }
...@@ -269,7 +269,7 @@ pptp_inbound_pkt(struct sk_buff *skb, ...@@ -269,7 +269,7 @@ pptp_inbound_pkt(struct sk_buff *skb,
struct nf_conn *ct, struct nf_conn *ct,
enum ip_conntrack_info ctinfo) enum ip_conntrack_info ctinfo)
{ {
struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; struct nf_ct_pptp_master *info = nfct_help_data(ct);
u_int16_t msg; u_int16_t msg;
__be16 cid = 0, pcid = 0; __be16 cid = 0, pcid = 0;
typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound; typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound;
...@@ -396,7 +396,7 @@ pptp_outbound_pkt(struct sk_buff *skb, ...@@ -396,7 +396,7 @@ pptp_outbound_pkt(struct sk_buff *skb,
struct nf_conn *ct, struct nf_conn *ct,
enum ip_conntrack_info ctinfo) enum ip_conntrack_info ctinfo)
{ {
struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; struct nf_ct_pptp_master *info = nfct_help_data(ct);
u_int16_t msg; u_int16_t msg;
__be16 cid = 0, pcid = 0; __be16 cid = 0, pcid = 0;
typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound; typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;
...@@ -506,7 +506,7 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, ...@@ -506,7 +506,7 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
{ {
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
const struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info; const struct nf_ct_pptp_master *info = nfct_help_data(ct);
const struct tcphdr *tcph; const struct tcphdr *tcph;
struct tcphdr _tcph; struct tcphdr _tcph;
const struct pptp_pkt_hdr *pptph; const struct pptp_pkt_hdr *pptph;
...@@ -592,6 +592,7 @@ static const struct nf_conntrack_expect_policy pptp_exp_policy = { ...@@ -592,6 +592,7 @@ static const struct nf_conntrack_expect_policy pptp_exp_policy = {
static struct nf_conntrack_helper pptp __read_mostly = { static struct nf_conntrack_helper pptp __read_mostly = {
.name = "pptp", .name = "pptp",
.me = THIS_MODULE, .me = THIS_MODULE,
.data_len = sizeof(struct nf_ct_pptp_master),
.tuple.src.l3num = AF_INET, .tuple.src.l3num = AF_INET,
.tuple.src.u.tcp.port = cpu_to_be16(PPTP_CONTROL_PORT), .tuple.src.u.tcp.port = cpu_to_be16(PPTP_CONTROL_PORT),
.tuple.dst.protonum = IPPROTO_TCP, .tuple.dst.protonum = IPPROTO_TCP,
......
...@@ -117,10 +117,10 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, ...@@ -117,10 +117,10 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct netns_proto_gre *net_gre = gre_pernet(net); struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
struct nf_ct_gre_keymap **kmp, *km; struct nf_ct_gre_keymap **kmp, *km;
kmp = &help->help.ct_pptp_info.keymap[dir]; kmp = &ct_pptp_info->keymap[dir];
if (*kmp) { if (*kmp) {
/* check whether it's a retransmission */ /* check whether it's a retransmission */
read_lock_bh(&net_gre->keymap_lock); read_lock_bh(&net_gre->keymap_lock);
...@@ -158,19 +158,19 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct) ...@@ -158,19 +158,19 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct netns_proto_gre *net_gre = gre_pernet(net); struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
enum ip_conntrack_dir dir; enum ip_conntrack_dir dir;
pr_debug("entering for ct %p\n", ct); pr_debug("entering for ct %p\n", ct);
write_lock_bh(&net_gre->keymap_lock); write_lock_bh(&net_gre->keymap_lock);
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
if (help->help.ct_pptp_info.keymap[dir]) { if (ct_pptp_info->keymap[dir]) {
pr_debug("removing %p from list\n", pr_debug("removing %p from list\n",
help->help.ct_pptp_info.keymap[dir]); ct_pptp_info->keymap[dir]);
list_del(&help->help.ct_pptp_info.keymap[dir]->list); list_del(&ct_pptp_info->keymap[dir]->list);
kfree(help->help.ct_pptp_info.keymap[dir]); kfree(ct_pptp_info->keymap[dir]);
help->help.ct_pptp_info.keymap[dir] = NULL; ct_pptp_info->keymap[dir] = NULL;
} }
} }
write_unlock_bh(&net_gre->keymap_lock); write_unlock_bh(&net_gre->keymap_lock);
......
...@@ -69,13 +69,12 @@ static int help(struct sk_buff *skb, ...@@ -69,13 +69,12 @@ static int help(struct sk_buff *skb,
void *sb_ptr; void *sb_ptr;
int ret = NF_ACCEPT; int ret = NF_ACCEPT;
int dir = CTINFO2DIR(ctinfo); int dir = CTINFO2DIR(ctinfo);
struct nf_ct_sane_master *ct_sane_info; struct nf_ct_sane_master *ct_sane_info = nfct_help_data(ct);
struct nf_conntrack_expect *exp; struct nf_conntrack_expect *exp;
struct nf_conntrack_tuple *tuple; struct nf_conntrack_tuple *tuple;
struct sane_request *req; struct sane_request *req;
struct sane_reply_net_start *reply; struct sane_reply_net_start *reply;
ct_sane_info = &nfct_help(ct)->help.ct_sane_info;
/* Until there's been traffic both ways, don't look in packets. */ /* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED && if (ctinfo != IP_CT_ESTABLISHED &&
ctinfo != IP_CT_ESTABLISHED_REPLY) ctinfo != IP_CT_ESTABLISHED_REPLY)
...@@ -203,6 +202,7 @@ static int __init nf_conntrack_sane_init(void) ...@@ -203,6 +202,7 @@ static int __init nf_conntrack_sane_init(void)
sane[i][0].tuple.src.l3num = PF_INET; sane[i][0].tuple.src.l3num = PF_INET;
sane[i][1].tuple.src.l3num = PF_INET6; sane[i][1].tuple.src.l3num = PF_INET6;
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
sane[i][j].data_len = sizeof(struct nf_ct_sane_master);
sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
sane[i][j].tuple.dst.protonum = IPPROTO_TCP; sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
sane[i][j].expect_policy = &sane_exp_policy; sane[i][j].expect_policy = &sane_exp_policy;
......
...@@ -1075,12 +1075,12 @@ static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, ...@@ -1075,12 +1075,12 @@ static int process_invite_response(struct sk_buff *skb, unsigned int dataoff,
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
if ((code >= 100 && code <= 199) || if ((code >= 100 && code <= 199) ||
(code >= 200 && code <= 299)) (code >= 200 && code <= 299))
return process_sdp(skb, dataoff, dptr, datalen, cseq); return process_sdp(skb, dataoff, dptr, datalen, cseq);
else if (help->help.ct_sip_info.invite_cseq == cseq) else if (ct_sip_info->invite_cseq == cseq)
flush_expectations(ct, true); flush_expectations(ct, true);
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -1091,12 +1091,12 @@ static int process_update_response(struct sk_buff *skb, unsigned int dataoff, ...@@ -1091,12 +1091,12 @@ static int process_update_response(struct sk_buff *skb, unsigned int dataoff,
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
if ((code >= 100 && code <= 199) || if ((code >= 100 && code <= 199) ||
(code >= 200 && code <= 299)) (code >= 200 && code <= 299))
return process_sdp(skb, dataoff, dptr, datalen, cseq); return process_sdp(skb, dataoff, dptr, datalen, cseq);
else if (help->help.ct_sip_info.invite_cseq == cseq) else if (ct_sip_info->invite_cseq == cseq)
flush_expectations(ct, true); flush_expectations(ct, true);
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -1107,12 +1107,12 @@ static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, ...@@ -1107,12 +1107,12 @@ static int process_prack_response(struct sk_buff *skb, unsigned int dataoff,
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
if ((code >= 100 && code <= 199) || if ((code >= 100 && code <= 199) ||
(code >= 200 && code <= 299)) (code >= 200 && code <= 299))
return process_sdp(skb, dataoff, dptr, datalen, cseq); return process_sdp(skb, dataoff, dptr, datalen, cseq);
else if (help->help.ct_sip_info.invite_cseq == cseq) else if (ct_sip_info->invite_cseq == cseq)
flush_expectations(ct, true); flush_expectations(ct, true);
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -1123,13 +1123,13 @@ static int process_invite_request(struct sk_buff *skb, unsigned int dataoff, ...@@ -1123,13 +1123,13 @@ static int process_invite_request(struct sk_buff *skb, unsigned int dataoff,
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
unsigned int ret; unsigned int ret;
flush_expectations(ct, true); flush_expectations(ct, true);
ret = process_sdp(skb, dataoff, dptr, datalen, cseq); ret = process_sdp(skb, dataoff, dptr, datalen, cseq);
if (ret == NF_ACCEPT) if (ret == NF_ACCEPT)
help->help.ct_sip_info.invite_cseq = cseq; ct_sip_info->invite_cseq = cseq;
return ret; return ret;
} }
...@@ -1154,7 +1154,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff, ...@@ -1154,7 +1154,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff,
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
unsigned int matchoff, matchlen; unsigned int matchoff, matchlen;
struct nf_conntrack_expect *exp; struct nf_conntrack_expect *exp;
...@@ -1235,7 +1235,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff, ...@@ -1235,7 +1235,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff,
store_cseq: store_cseq:
if (ret == NF_ACCEPT) if (ret == NF_ACCEPT)
help->help.ct_sip_info.register_cseq = cseq; ct_sip_info->register_cseq = cseq;
return ret; return ret;
} }
...@@ -1245,7 +1245,7 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff, ...@@ -1245,7 +1245,7 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff,
{ {
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo); struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
struct nf_conn_help *help = nfct_help(ct); struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
union nf_inet_addr addr; union nf_inet_addr addr;
__be16 port; __be16 port;
...@@ -1262,7 +1262,7 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff, ...@@ -1262,7 +1262,7 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff,
* responses, so we store the sequence number of the last valid * responses, so we store the sequence number of the last valid
* request and compare it here. * request and compare it here.
*/ */
if (help->help.ct_sip_info.register_cseq != cseq) if (ct_sip_info->register_cseq != cseq)
return NF_ACCEPT; return NF_ACCEPT;
if (code >= 100 && code <= 199) if (code >= 100 && code <= 199)
...@@ -1578,6 +1578,7 @@ static int __init nf_conntrack_sip_init(void) ...@@ -1578,6 +1578,7 @@ static int __init nf_conntrack_sip_init(void)
sip[i][3].help = sip_help_tcp; sip[i][3].help = sip_help_tcp;
for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { for (j = 0; j < ARRAY_SIZE(sip[i]); j++) {
sip[i][j].data_len = sizeof(struct nf_ct_sip_master);
sip[i][j].tuple.src.u.udp.port = htons(ports[i]); sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
sip[i][j].expect_policy = sip_exp_policy; sip[i][j].expect_policy = sip_exp_policy;
sip[i][j].expect_class_max = SIP_EXPECT_MAX; sip[i][j].expect_class_max = SIP_EXPECT_MAX;
......
...@@ -112,6 +112,8 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) ...@@ -112,6 +112,8 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
goto err3; goto err3;
if (info->helper[0]) { if (info->helper[0]) {
struct nf_conntrack_helper *helper;
ret = -ENOENT; ret = -ENOENT;
proto = xt_ct_find_proto(par); proto = xt_ct_find_proto(par);
if (!proto) { if (!proto) {
...@@ -120,19 +122,21 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) ...@@ -120,19 +122,21 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
goto err3; goto err3;
} }
ret = -ENOMEM;
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
if (help == NULL)
goto err3;
ret = -ENOENT; ret = -ENOENT;
help->helper = nf_conntrack_helper_try_module_get(info->helper, helper = nf_conntrack_helper_try_module_get(info->helper,
par->family, par->family,
proto); proto);
if (help->helper == NULL) { if (helper == NULL) {
pr_info("No such helper \"%s\"\n", info->helper); pr_info("No such helper \"%s\"\n", info->helper);
goto err3; goto err3;
} }
ret = -ENOMEM;
help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
if (help == NULL)
goto err3;
help->helper = helper;
} }
__set_bit(IPS_TEMPLATE_BIT, &ct->status); __set_bit(IPS_TEMPLATE_BIT, &ct->status);
...@@ -202,6 +206,8 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) ...@@ -202,6 +206,8 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
goto err3; goto err3;
if (info->helper[0]) { if (info->helper[0]) {
struct nf_conntrack_helper *helper;
ret = -ENOENT; ret = -ENOENT;
proto = xt_ct_find_proto(par); proto = xt_ct_find_proto(par);
if (!proto) { if (!proto) {
...@@ -210,19 +216,21 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) ...@@ -210,19 +216,21 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
goto err3; goto err3;
} }
ret = -ENOMEM;
help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
if (help == NULL)
goto err3;
ret = -ENOENT; ret = -ENOENT;
help->helper = nf_conntrack_helper_try_module_get(info->helper, helper = nf_conntrack_helper_try_module_get(info->helper,
par->family, par->family,
proto); proto);
if (help->helper == NULL) { if (helper == NULL) {
pr_info("No such helper \"%s\"\n", info->helper); pr_info("No such helper \"%s\"\n", info->helper);
goto err3; goto err3;
} }
ret = -ENOMEM;
help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
if (help == NULL)
goto err3;
help->helper = helper;
} }
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment