Linux Audio

Check our new training course

Loading...
  1/*
  2 * This module is used to copy security markings from packets
  3 * to connections, and restore security markings from connections
  4 * back to packets.  This would normally be performed in conjunction
  5 * with the SECMARK target and state match.
  6 *
  7 * Based somewhat on CONNMARK:
  8 *   Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
  9 *    by Henrik Nordstrom <hno@marasystems.com>
 10 *
 11 * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
 12 *
 13 * This program is free software; you can redistribute it and/or modify
 14 * it under the terms of the GNU General Public License version 2 as
 15 * published by the Free Software Foundation.
 16 *
 17 */
 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 19#include <linux/module.h>
 20#include <linux/skbuff.h>
 21#include <linux/netfilter/x_tables.h>
 22#include <linux/netfilter/xt_CONNSECMARK.h>
 23#include <net/netfilter/nf_conntrack.h>
 24#include <net/netfilter/nf_conntrack_ecache.h>
 25
 26MODULE_LICENSE("GPL");
 27MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
 28MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark");
 29MODULE_ALIAS("ipt_CONNSECMARK");
 30MODULE_ALIAS("ip6t_CONNSECMARK");
 31
 32/*
 33 * If the packet has a security mark and the connection does not, copy
 34 * the security mark from the packet to the connection.
 35 */
 36static void secmark_save(const struct sk_buff *skb)
 37{
 38	if (skb->secmark) {
 39		struct nf_conn *ct;
 40		enum ip_conntrack_info ctinfo;
 41
 42		ct = nf_ct_get(skb, &ctinfo);
 43		if (ct && !ct->secmark) {
 44			ct->secmark = skb->secmark;
 45			nf_conntrack_event_cache(IPCT_SECMARK, ct);
 46		}
 47	}
 48}
 49
 50/*
 51 * If packet has no security mark, and the connection does, restore the
 52 * security mark from the connection to the packet.
 53 */
 54static void secmark_restore(struct sk_buff *skb)
 55{
 56	if (!skb->secmark) {
 57		const struct nf_conn *ct;
 58		enum ip_conntrack_info ctinfo;
 59
 60		ct = nf_ct_get(skb, &ctinfo);
 61		if (ct && ct->secmark)
 62			skb->secmark = ct->secmark;
 63	}
 64}
 65
 66static unsigned int
 67connsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
 68{
 69	const struct xt_connsecmark_target_info *info = par->targinfo;
 70
 71	switch (info->mode) {
 72	case CONNSECMARK_SAVE:
 73		secmark_save(skb);
 74		break;
 75
 76	case CONNSECMARK_RESTORE:
 77		secmark_restore(skb);
 78		break;
 79
 80	default:
 81		BUG();
 82	}
 83
 84	return XT_CONTINUE;
 85}
 86
 87static int connsecmark_tg_check(const struct xt_tgchk_param *par)
 88{
 89	const struct xt_connsecmark_target_info *info = par->targinfo;
 90	int ret;
 91
 92	if (strcmp(par->table, "mangle") != 0 &&
 93	    strcmp(par->table, "security") != 0) {
 94		pr_info("target only valid in the \'mangle\' "
 95			"or \'security\' tables, not \'%s\'.\n", par->table);
 96		return -EINVAL;
 97	}
 98
 99	switch (info->mode) {
100	case CONNSECMARK_SAVE:
101	case CONNSECMARK_RESTORE:
102		break;
103
104	default:
105		pr_info("invalid mode: %hu\n", info->mode);
106		return -EINVAL;
107	}
108
109	ret = nf_ct_l3proto_try_module_get(par->family);
110	if (ret < 0)
111		pr_info("cannot load conntrack support for proto=%u\n",
112			par->family);
113	return ret;
114}
115
116static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
117{
118	nf_ct_l3proto_module_put(par->family);
119}
120
121static struct xt_target connsecmark_tg_reg __read_mostly = {
122	.name       = "CONNSECMARK",
123	.revision   = 0,
124	.family     = NFPROTO_UNSPEC,
125	.checkentry = connsecmark_tg_check,
126	.destroy    = connsecmark_tg_destroy,
127	.target     = connsecmark_tg,
128	.targetsize = sizeof(struct xt_connsecmark_target_info),
129	.me         = THIS_MODULE,
130};
131
132static int __init connsecmark_tg_init(void)
133{
134	return xt_register_target(&connsecmark_tg_reg);
135}
136
137static void __exit connsecmark_tg_exit(void)
138{
139	xt_unregister_target(&connsecmark_tg_reg);
140}
141
142module_init(connsecmark_tg_init);
143module_exit(connsecmark_tg_exit);