static int check(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) { const struct xt_connbytes_info *sinfo = matchinfo; if (sinfo->what != XT_CONNBYTES_PKTS && sinfo->what != XT_CONNBYTES_BYTES && sinfo->what != XT_CONNBYTES_AVGPKT) return 0; if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && sinfo->direction != XT_CONNBYTES_DIR_REPLY && sinfo->direction != XT_CONNBYTES_DIR_BOTH) return 0; if (nf_ct_l3proto_try_module_get(match->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%d\n", match->family); return 0; } return 1; }
int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto) { int err; err = nf_ct_l3proto_try_module_get(l3proto->l3proto); if (err < 0) return err; mutex_lock(&nf_nat_proto_mutex); RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_TCP], &nf_nat_l4proto_tcp); RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP], &nf_nat_l4proto_udp); #ifdef CONFIG_NF_NAT_PROTO_DCCP RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_DCCP], &nf_nat_l4proto_dccp); #endif #ifdef CONFIG_NF_NAT_PROTO_SCTP RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_SCTP], &nf_nat_l4proto_sctp); #endif #ifdef CONFIG_NF_NAT_PROTO_UDPLITE RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDPLITE], &nf_nat_l4proto_udplite); #endif mutex_unlock(&nf_nat_proto_mutex); RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto); return 0; }
static bool connsecmark_tg_check(const struct xt_tgchk_param *par) { const struct xt_connsecmark_target_info *info = par->targinfo; if (strcmp(par->table, "mangle") != 0 && strcmp(par->table, "security") != 0) { printk(KERN_INFO PFX "target only valid in the \'mangle\' " "or \'security\' tables, not \'%s\'.\n", par->table); return false; } switch (info->mode) { case CONNSECMARK_SAVE: case CONNSECMARK_RESTORE: break; default: printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); return false; } if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->family); return false; } return true; }
static bool connbytes_mt_check(const struct xt_mtchk_param *par) { const struct xt_connbytes_info *sinfo = par->matchinfo; if (sinfo->what != XT_CONNBYTES_PKTS && sinfo->what != XT_CONNBYTES_BYTES && sinfo->what != XT_CONNBYTES_AVGPKT) return false; if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && sinfo->direction != XT_CONNBYTES_DIR_REPLY && sinfo->direction != XT_CONNBYTES_DIR_BOTH) return false; if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->family); return false; } /* * This filter cannot function correctly unless connection tracking * accounting is enabled, so complain in the hope that someone notices. */ if (!nf_ct_acct_enabled(&init_net)) { pr_warning("Forcing CT accounting to be enabled\n"); nf_ct_set_acct(&init_net, true); } return true; }
static int connsecmark_tg_check(const struct xt_tgchk_param *par) { const struct xt_connsecmark_target_info *info = par->targinfo; int ret; if (strcmp(par->table, "mangle") != 0 && strcmp(par->table, "security") != 0) { pr_info("target only valid in the \'mangle\' " "or \'security\' tables, not \'%s\'.\n", par->table); return -EINVAL; } switch (info->mode) { case CONNSECMARK_SAVE: case CONNSECMARK_RESTORE: break; default: pr_info("invalid mode: %hu\n", info->mode); return -EINVAL; } ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) pr_info("cannot load conntrack support for proto=%u\n", par->family); return ret; }
static int connbytes_mt_check(const struct xt_mtchk_param *par) { const struct xt_connbytes_info *sinfo = par->matchinfo; int ret; if (sinfo->what != XT_CONNBYTES_PKTS && sinfo->what != XT_CONNBYTES_BYTES && sinfo->what != XT_CONNBYTES_AVGPKT) return -EINVAL; if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && sinfo->direction != XT_CONNBYTES_DIR_REPLY && sinfo->direction != XT_CONNBYTES_DIR_BOTH) return -EINVAL; ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) pr_info("cannot load conntrack support for proto=%u\n", par->family); /* * This filter cannot function correctly unless connection tracking * accounting is enabled, so complain in the hope that someone notices. */ if (!nf_ct_acct_enabled(par->net)) { pr_warning("Forcing CT accounting to be enabled\n"); nf_ct_set_acct(par->net, true); } return ret; }
static int nf_ct_netns_do_get(struct net *net, u8 nfproto) { const struct nf_conntrack_l3proto *l3proto; int ret; might_sleep(); ret = nf_ct_l3proto_try_module_get(nfproto); if (ret < 0) return ret; /* we already have a reference, can't fail */ rcu_read_lock(); l3proto = __nf_ct_l3proto_find(nfproto); rcu_read_unlock(); if (!l3proto->net_ns_get) return 0; ret = l3proto->net_ns_get(net); if (ret < 0) nf_ct_l3proto_module_put(nfproto); return ret; }
static bool checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, unsigned int hook_mask) { const struct xt_connmark_target_info *matchinfo = targinfo; if (nf_ct_l3proto_try_module_get(target->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%d\n", target->family); return false; } if (matchinfo->mode == XT_CONNMARK_RESTORE) { if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "CONNMARK: restore can only be " "called from \"mangle\" table, not \"%s\"\n", tablename); return false; } } if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); return false; } return true; }
static int xt_ct_tg_check(const struct xt_tgchk_param *par, struct xt_ct_target_info_v1 *info) { struct nf_conntrack_tuple t; struct nf_conn *ct; int ret = -EOPNOTSUPP; if (info->flags & XT_CT_NOTRACK) { ct = NULL; goto out; } #ifndef CONFIG_NF_CONNTRACK_ZONES if (info->zone) goto err1; #endif ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) goto err1; memset(&t, 0, sizeof(t)); ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); ret = PTR_ERR(ct); if (IS_ERR(ct)) goto err2; ret = 0; if ((info->ct_events || info->exp_events) && !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, GFP_KERNEL)) { ret = -EINVAL; goto err3; } if (info->helper[0]) { ret = xt_ct_set_helper(ct, info->helper, par); if (ret < 0) goto err3; } if (info->timeout[0]) { ret = xt_ct_set_timeout(ct, par, info->timeout); if (ret < 0) goto err3; } nf_conntrack_tmpl_insert(par->net, ct); out: info->ct = ct; return 0; err3: nf_conntrack_free(ct); err2: nf_ct_l3proto_module_put(par->family); err1: return ret; }
static int state_mt_check(const struct xt_mtchk_param *par) { if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->match->family); return false; } return true; }
static bool connmark_tg_check(const struct xt_tgchk_param *par) { if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "cannot load conntrack support for " "proto=%u\n", par->family); return false; } return true; }
static int state_mt_check(const struct xt_mtchk_param *par) { int ret; ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) pr_info("cannot load conntrack support for proto=%u\n", par->family); return ret; }
int nat64_tg_check(const struct xt_tgchk_param *par) { int ret; ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) pr_info("cannot load support for proto=%u\n", par->family); return ret; }
static int synproxy_tg4_check(const struct xt_tgchk_param *par) { const struct ipt_entry *e = par->entryinfo; if (e->ip.proto != IPPROTO_TCP || e->ip.invflags & XT_INV_PROTO) return -EINVAL; return nf_ct_l3proto_try_module_get(par->family); }
static bool conntrack_mt_check(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) { if (nf_ct_l3proto_try_module_get(match->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", match->family); return false; } return true; }
static int helper_mt_check(const struct xt_mtchk_param *par) { struct xt_helper_info *info = par->matchinfo; if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->family); return false; } info->name[29] = '\0'; return true; }
static int helper_mt_check(const struct xt_mtchk_param *par) { struct xt_helper_info *info = par->matchinfo; int ret; ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) { pr_info("cannot load conntrack support for proto=%u\n", par->family); return ret; } info->name[29] = '\0'; return 0; }
static int nft_ct_l3proto_try_module_get(uint8_t family) { int err; if (family == NFPROTO_INET) { err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4); if (err < 0) goto err1; err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6); if (err < 0) goto err2; } else { err = nf_ct_l3proto_try_module_get(family); if (err < 0) goto err1; } return 0; err2: nf_ct_l3proto_module_put(NFPROTO_IPV4); err1: return err; }
static bool connmark_mt_check_v0(const struct xt_mtchk_param *par) { const struct xt_connmark_info *cm = par->matchinfo; if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { printk(KERN_WARNING "connmark: only support 32bit mark\n"); return false; } if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->family); return false; } return true; }
static int checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) if (nf_ct_l3proto_try_module_get(match->family) < 0) { printk(KERN_WARNING "can't load nf_conntrack support for " "proto=%d\n", match->family); return 0; } #endif return 1; }
int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto) { int err; err = nf_ct_l3proto_try_module_get(l3proto->l3proto); if (err < 0) return err; mutex_lock(&nf_nat_proto_mutex); RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_TCP], &nf_nat_l4proto_tcp); RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP], &nf_nat_l4proto_udp); mutex_unlock(&nf_nat_proto_mutex); RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto); return 0; }
static int checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) { struct xt_connmark_info *cm = matchinfo; if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { printk(KERN_WARNING "connmark: only support 32bit mark\n"); return 0; } if (nf_ct_l3proto_try_module_get(match->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%d\n", match->family); return 0; } return 1; }
static bool csecmark_tg_check(const struct xt_tgchk_param *par) { const struct xt_connsecmark_target_info *info = par->targinfo; if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->family); return false; } switch (info->mode) { case CONNSECMARK_SAVE: case CONNSECMARK_RESTORE: break; default: printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); return false; } return true; }
static int connbytes_mt_check(const struct xt_mtchk_param *par) { const struct xt_connbytes_info *sinfo = par->matchinfo; int ret; if (sinfo->what != XT_CONNBYTES_PKTS && sinfo->what != XT_CONNBYTES_BYTES && sinfo->what != XT_CONNBYTES_AVGPKT) return -EINVAL; if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && sinfo->direction != XT_CONNBYTES_DIR_REPLY && sinfo->direction != XT_CONNBYTES_DIR_BOTH) return -EINVAL; ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) pr_info("cannot load conntrack support for proto=%u\n", par->family); return ret; }
static int connbytes_mt_check(const struct xt_mtchk_param *par) { const struct xt_connbytes_info *sinfo = par->matchinfo; if (sinfo->what != XT_CONNBYTES_PKTS && sinfo->what != XT_CONNBYTES_BYTES && sinfo->what != XT_CONNBYTES_AVGPKT) return false; if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && sinfo->direction != XT_CONNBYTES_DIR_REPLY && sinfo->direction != XT_CONNBYTES_DIR_BOTH) return false; if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%u\n", par->family); return false; } return true; }
static bool checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, unsigned int hook_mask) { const struct xt_connsecmark_target_info *info = targinfo; if (nf_ct_l3proto_try_module_get(target->family) < 0) { printk(KERN_WARNING "can't load conntrack support for " "proto=%d\n", target->family); return false; } switch (info->mode) { case CONNSECMARK_SAVE: case CONNSECMARK_RESTORE: break; default: printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); return false; } return true; }
static int nft_ct_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) { struct nft_ct *priv = nft_expr_priv(expr); int err; if (tb[NFTA_CT_DREG] == NULL || tb[NFTA_CT_KEY] == NULL) return -EINVAL; priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY])); if (tb[NFTA_CT_DIRECTION] != NULL) { priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]); switch (priv->dir) { case IP_CT_DIR_ORIGINAL: case IP_CT_DIR_REPLY: break; default: return -EINVAL; } } switch (priv->key) { case NFT_CT_STATE: case NFT_CT_DIRECTION: case NFT_CT_STATUS: #ifdef CONFIG_NF_CONNTRACK_MARK case NFT_CT_MARK: #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK case NFT_CT_SECMARK: #endif case NFT_CT_EXPIRATION: case NFT_CT_HELPER: if (tb[NFTA_CT_DIRECTION] != NULL) return -EINVAL; break; case NFT_CT_PROTOCOL: case NFT_CT_SRC: case NFT_CT_DST: case NFT_CT_PROTO_SRC: case NFT_CT_PROTO_DST: if (tb[NFTA_CT_DIRECTION] == NULL) return -EINVAL; break; default: return -EOPNOTSUPP; } err = nf_ct_l3proto_try_module_get(ctx->afi->family); if (err < 0) return err; priv->family = ctx->afi->family; priv->dreg = ntohl(nla_get_be32(tb[NFTA_CT_DREG])); err = nft_validate_output_register(priv->dreg); if (err < 0) goto err1; err = nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE); if (err < 0) goto err1; return 0; err1: nf_ct_l3proto_module_put(ctx->afi->family); return err; }
static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) { struct xt_ct_target_info_v1 *info = par->targinfo; struct nf_conntrack_tuple t; struct nf_conn_help *help; struct nf_conn *ct; int ret = 0; u8 proto; #ifdef CONFIG_NF_CONNTRACK_TIMEOUT struct ctnl_timeout *timeout; #endif if (info->flags & ~XT_CT_NOTRACK) return -EINVAL; if (info->flags & XT_CT_NOTRACK) { ct = nf_ct_untracked_get(); atomic_inc(&ct->ct_general.use); goto out; } #ifndef CONFIG_NF_CONNTRACK_ZONES if (info->zone) goto err1; #endif ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) goto err1; memset(&t, 0, sizeof(t)); ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); ret = PTR_ERR(ct); if (IS_ERR(ct)) goto err2; ret = 0; if ((info->ct_events || info->exp_events) && !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, GFP_KERNEL)) goto err3; if (info->helper[0]) { ret = -ENOENT; proto = xt_ct_find_proto(par); if (!proto) { pr_info("You must specify a L4 protocol, " "and not use inversions on it.\n"); goto err3; } ret = -ENOMEM; help = nf_ct_helper_ext_add(ct, GFP_KERNEL); if (help == NULL) goto err3; ret = -ENOENT; help->helper = nf_conntrack_helper_try_module_get(info->helper, par->family, proto); if (help->helper == NULL) { pr_info("No such helper \"%s\"\n", info->helper); goto err3; } } #ifdef CONFIG_NF_CONNTRACK_TIMEOUT if (info->timeout[0]) { typeof(nf_ct_timeout_find_get_hook) timeout_find_get; struct nf_conn_timeout *timeout_ext; rcu_read_lock(); timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); if (timeout_find_get) { const struct ipt_entry *e = par->entryinfo; struct nf_conntrack_l4proto *l4proto; if (e->ip.invflags & IPT_INV_PROTO) { ret = -EINVAL; pr_info("You cannot use inversion on " "L4 protocol\n"); goto err4; } timeout = timeout_find_get(info->timeout); if (timeout == NULL) { ret = -ENOENT; pr_info("No such timeout policy \"%s\"\n", info->timeout); goto err4; } if (timeout->l3num != par->family) { ret = -EINVAL; pr_info("Timeout policy `%s' can only be " "used by L3 protocol number %d\n", info->timeout, timeout->l3num); goto err5; } /* Make sure the timeout policy matches any existing * protocol tracker, otherwise default to generic. */ l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); if (timeout->l4proto->l4proto != l4proto->l4proto) { ret = -EINVAL; pr_info("Timeout policy `%s' can only be " "used by L4 protocol number %d\n", info->timeout, timeout->l4proto->l4proto); goto err5; } timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); if (timeout_ext == NULL) { ret = -ENOMEM; goto err5; } } else { ret = -ENOENT; pr_info("Timeout policy base is empty\n"); goto err4; } rcu_read_unlock(); } #endif __set_bit(IPS_TEMPLATE_BIT, &ct->status); __set_bit(IPS_CONFIRMED_BIT, &ct->status); out: info->ct = ct; return 0; #ifdef CONFIG_NF_CONNTRACK_TIMEOUT err5: __xt_ct_tg_timeout_put(timeout); err4: rcu_read_unlock(); #endif err3: nf_conntrack_free(ct); err2: nf_ct_l3proto_module_put(par->family); err1: return ret; }
static int xt_ct_tg_check(const struct xt_tgchk_param *par) { struct xt_ct_target_info *info = par->targinfo; struct nf_conntrack_tuple t; struct nf_conn_help *help; struct nf_conn *ct; int ret = 0; u8 proto; if (info->flags & ~XT_CT_NOTRACK) return -EINVAL; if (info->flags & XT_CT_NOTRACK) { ct = nf_ct_untracked_get(); atomic_inc(&ct->ct_general.use); goto out; } #ifndef CONFIG_NF_CONNTRACK_ZONES if (info->zone) goto err1; #endif ret = nf_ct_l3proto_try_module_get(par->family); if (ret < 0) goto err1; memset(&t, 0, sizeof(t)); ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); ret = PTR_ERR(ct); if (IS_ERR(ct)) goto err2; ret = 0; if ((info->ct_events || info->exp_events) && !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, GFP_KERNEL)) goto err3; if (info->helper[0]) { ret = -ENOENT; proto = xt_ct_find_proto(par); if (!proto) goto err3; ret = -ENOMEM; help = nf_ct_helper_ext_add(ct, GFP_KERNEL); if (help == NULL) goto err3; ret = -ENOENT; help->helper = nf_conntrack_helper_try_module_get(info->helper, par->family, proto); if (help->helper == NULL) goto err3; } __set_bit(IPS_TEMPLATE_BIT, &ct->status); __set_bit(IPS_CONFIRMED_BIT, &ct->status); out: info->ct = ct; return 0; err3: nf_conntrack_free(ct); err2: nf_ct_l3proto_module_put(par->family); err1: return ret; }