0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 #include <linux/module.h>
0016 #include <linux/skbuff.h>
0017 #include <linux/netfilter/x_tables.h>
0018 #include <linux/netfilter/xt_CONNSECMARK.h>
0019 #include <net/netfilter/nf_conntrack.h>
0020 #include <net/netfilter/nf_conntrack_ecache.h>
0021
0022 MODULE_LICENSE("GPL");
0023 MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
0024 MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark");
0025 MODULE_ALIAS("ipt_CONNSECMARK");
0026 MODULE_ALIAS("ip6t_CONNSECMARK");
0027
0028
0029
0030
0031
0032 static void secmark_save(const struct sk_buff *skb)
0033 {
0034 if (skb->secmark) {
0035 struct nf_conn *ct;
0036 enum ip_conntrack_info ctinfo;
0037
0038 ct = nf_ct_get(skb, &ctinfo);
0039 if (ct && !ct->secmark) {
0040 ct->secmark = skb->secmark;
0041 nf_conntrack_event_cache(IPCT_SECMARK, ct);
0042 }
0043 }
0044 }
0045
0046
0047
0048
0049
0050 static void secmark_restore(struct sk_buff *skb)
0051 {
0052 if (!skb->secmark) {
0053 const struct nf_conn *ct;
0054 enum ip_conntrack_info ctinfo;
0055
0056 ct = nf_ct_get(skb, &ctinfo);
0057 if (ct && ct->secmark)
0058 skb->secmark = ct->secmark;
0059 }
0060 }
0061
0062 static unsigned int
0063 connsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
0064 {
0065 const struct xt_connsecmark_target_info *info = par->targinfo;
0066
0067 switch (info->mode) {
0068 case CONNSECMARK_SAVE:
0069 secmark_save(skb);
0070 break;
0071
0072 case CONNSECMARK_RESTORE:
0073 secmark_restore(skb);
0074 break;
0075
0076 default:
0077 BUG();
0078 }
0079
0080 return XT_CONTINUE;
0081 }
0082
0083 static int connsecmark_tg_check(const struct xt_tgchk_param *par)
0084 {
0085 const struct xt_connsecmark_target_info *info = par->targinfo;
0086 int ret;
0087
0088 if (strcmp(par->table, "mangle") != 0 &&
0089 strcmp(par->table, "security") != 0) {
0090 pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
0091 par->table);
0092 return -EINVAL;
0093 }
0094
0095 switch (info->mode) {
0096 case CONNSECMARK_SAVE:
0097 case CONNSECMARK_RESTORE:
0098 break;
0099
0100 default:
0101 pr_info_ratelimited("invalid mode: %hu\n", info->mode);
0102 return -EINVAL;
0103 }
0104
0105 ret = nf_ct_netns_get(par->net, par->family);
0106 if (ret < 0)
0107 pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
0108 par->family);
0109 return ret;
0110 }
0111
0112 static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
0113 {
0114 nf_ct_netns_put(par->net, par->family);
0115 }
0116
0117 static struct xt_target connsecmark_tg_reg __read_mostly = {
0118 .name = "CONNSECMARK",
0119 .revision = 0,
0120 .family = NFPROTO_UNSPEC,
0121 .checkentry = connsecmark_tg_check,
0122 .destroy = connsecmark_tg_destroy,
0123 .target = connsecmark_tg,
0124 .targetsize = sizeof(struct xt_connsecmark_target_info),
0125 .me = THIS_MODULE,
0126 };
0127
0128 static int __init connsecmark_tg_init(void)
0129 {
0130 return xt_register_target(&connsecmark_tg_reg);
0131 }
0132
0133 static void __exit connsecmark_tg_exit(void)
0134 {
0135 xt_unregister_target(&connsecmark_tg_reg);
0136 }
0137
0138 module_init(connsecmark_tg_init);
0139 module_exit(connsecmark_tg_exit);