1100468e9SJames Morris /* 2100468e9SJames Morris * This module is used to copy security markings from packets 3100468e9SJames Morris * to connections, and restore security markings from connections 4100468e9SJames Morris * back to packets. This would normally be performed in conjunction 5100468e9SJames Morris * with the SECMARK target and state match. 6100468e9SJames Morris * 7100468e9SJames Morris * Based somewhat on CONNMARK: 8100468e9SJames Morris * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 9100468e9SJames Morris * by Henrik Nordstrom <hno@marasystems.com> 10100468e9SJames Morris * 11100468e9SJames Morris * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> 12100468e9SJames Morris * 13100468e9SJames Morris * This program is free software; you can redistribute it and/or modify 14100468e9SJames Morris * it under the terms of the GNU General Public License version 2 as 15100468e9SJames Morris * published by the Free Software Foundation. 16100468e9SJames Morris * 17100468e9SJames Morris */ 18100468e9SJames Morris #include <linux/module.h> 19100468e9SJames Morris #include <linux/skbuff.h> 20100468e9SJames Morris #include <linux/netfilter/x_tables.h> 21100468e9SJames Morris #include <linux/netfilter/xt_CONNSECMARK.h> 22100468e9SJames Morris #include <net/netfilter/nf_conntrack_compat.h> 23100468e9SJames Morris 24100468e9SJames Morris #define PFX "CONNSECMARK: " 25100468e9SJames Morris 26100468e9SJames Morris MODULE_LICENSE("GPL"); 27100468e9SJames Morris MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); 28100468e9SJames Morris MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module"); 29100468e9SJames Morris MODULE_ALIAS("ipt_CONNSECMARK"); 30100468e9SJames Morris MODULE_ALIAS("ip6t_CONNSECMARK"); 31100468e9SJames Morris 32100468e9SJames Morris /* 33100468e9SJames Morris * If the packet has a security mark and the connection does not, copy 34100468e9SJames Morris * the security mark from the packet to the connection. 35100468e9SJames Morris */ 36100468e9SJames Morris static void secmark_save(struct sk_buff *skb) 37100468e9SJames Morris { 38100468e9SJames Morris if (skb->secmark) { 39100468e9SJames Morris u32 *connsecmark; 40100468e9SJames Morris enum ip_conntrack_info ctinfo; 41100468e9SJames Morris 42100468e9SJames Morris connsecmark = nf_ct_get_secmark(skb, &ctinfo); 43100468e9SJames Morris if (connsecmark && !*connsecmark) 44100468e9SJames Morris if (*connsecmark != skb->secmark) 45100468e9SJames Morris *connsecmark = skb->secmark; 46100468e9SJames Morris } 47100468e9SJames Morris } 48100468e9SJames Morris 49100468e9SJames Morris /* 50100468e9SJames Morris * If packet has no security mark, and the connection does, restore the 51100468e9SJames Morris * security mark from the connection to the packet. 52100468e9SJames Morris */ 53100468e9SJames Morris static void secmark_restore(struct sk_buff *skb) 54100468e9SJames Morris { 55100468e9SJames Morris if (!skb->secmark) { 56100468e9SJames Morris u32 *connsecmark; 57100468e9SJames Morris enum ip_conntrack_info ctinfo; 58100468e9SJames Morris 59100468e9SJames Morris connsecmark = nf_ct_get_secmark(skb, &ctinfo); 60100468e9SJames Morris if (connsecmark && *connsecmark) 61100468e9SJames Morris if (skb->secmark != *connsecmark) 62100468e9SJames Morris skb->secmark = *connsecmark; 63100468e9SJames Morris } 64100468e9SJames Morris } 65100468e9SJames Morris 66100468e9SJames Morris static unsigned int target(struct sk_buff **pskb, const struct net_device *in, 67100468e9SJames Morris const struct net_device *out, unsigned int hooknum, 68100468e9SJames Morris const struct xt_target *target, 69fe1cb108SPatrick McHardy const void *targinfo) 70100468e9SJames Morris { 71100468e9SJames Morris struct sk_buff *skb = *pskb; 72100468e9SJames Morris const struct xt_connsecmark_target_info *info = targinfo; 73100468e9SJames Morris 74100468e9SJames Morris switch (info->mode) { 75100468e9SJames Morris case CONNSECMARK_SAVE: 76100468e9SJames Morris secmark_save(skb); 77100468e9SJames Morris break; 78100468e9SJames Morris 79100468e9SJames Morris case CONNSECMARK_RESTORE: 80100468e9SJames Morris secmark_restore(skb); 81100468e9SJames Morris break; 82100468e9SJames Morris 83100468e9SJames Morris default: 84100468e9SJames Morris BUG(); 85100468e9SJames Morris } 86100468e9SJames Morris 87100468e9SJames Morris return XT_CONTINUE; 88100468e9SJames Morris } 89100468e9SJames Morris 90100468e9SJames Morris static int checkentry(const char *tablename, const void *entry, 91100468e9SJames Morris const struct xt_target *target, void *targinfo, 92efa74165SPatrick McHardy unsigned int hook_mask) 93100468e9SJames Morris { 94100468e9SJames Morris struct xt_connsecmark_target_info *info = targinfo; 95100468e9SJames Morris 96100468e9SJames Morris switch (info->mode) { 97100468e9SJames Morris case CONNSECMARK_SAVE: 98100468e9SJames Morris case CONNSECMARK_RESTORE: 99100468e9SJames Morris break; 100100468e9SJames Morris 101100468e9SJames Morris default: 102100468e9SJames Morris printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); 103100468e9SJames Morris return 0; 104100468e9SJames Morris } 105100468e9SJames Morris 106100468e9SJames Morris return 1; 107100468e9SJames Morris } 108100468e9SJames Morris 1094470bbc7SPatrick McHardy static struct xt_target xt_connsecmark_target[] = { 1104470bbc7SPatrick McHardy { 111100468e9SJames Morris .name = "CONNSECMARK", 112100468e9SJames Morris .family = AF_INET, 1134470bbc7SPatrick McHardy .checkentry = checkentry, 114100468e9SJames Morris .target = target, 115100468e9SJames Morris .targetsize = sizeof(struct xt_connsecmark_target_info), 116100468e9SJames Morris .table = "mangle", 117100468e9SJames Morris .me = THIS_MODULE, 1184470bbc7SPatrick McHardy }, 1194470bbc7SPatrick McHardy { 1204470bbc7SPatrick McHardy .name = "CONNSECMARK", 121100468e9SJames Morris .family = AF_INET6, 1224470bbc7SPatrick McHardy .checkentry = checkentry, 1234470bbc7SPatrick McHardy .target = target, 1244470bbc7SPatrick McHardy .targetsize = sizeof(struct xt_connsecmark_target_info), 1254470bbc7SPatrick McHardy .table = "mangle", 1264470bbc7SPatrick McHardy .me = THIS_MODULE, 1274470bbc7SPatrick McHardy }, 128100468e9SJames Morris }; 129100468e9SJames Morris 130100468e9SJames Morris static int __init xt_connsecmark_init(void) 131100468e9SJames Morris { 132100468e9SJames Morris need_conntrack(); 1334470bbc7SPatrick McHardy return xt_register_targets(xt_connsecmark_targets, 1344470bbc7SPatrick McHardy ARRAY_SIZE(xt_connsecmark_targets)); 135100468e9SJames Morris } 136100468e9SJames Morris 137100468e9SJames Morris static void __exit xt_connsecmark_fini(void) 138100468e9SJames Morris { 1394470bbc7SPatrick McHardy xt_unregister_targets(xt_connsecmark_targets, 1404470bbc7SPatrick McHardy ARRAY_SIZE(xt_connsecmark_targets)); 141100468e9SJames Morris } 142100468e9SJames Morris 143100468e9SJames Morris module_init(xt_connsecmark_init); 144100468e9SJames Morris module_exit(xt_connsecmark_fini); 145