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> 22587aa641SPatrick McHardy #include <net/netfilter/nf_conntrack.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 */ 36a47362a2SJan Engelhardt static void secmark_save(const struct sk_buff *skb) 37100468e9SJames Morris { 38100468e9SJames Morris if (skb->secmark) { 39587aa641SPatrick McHardy struct nf_conn *ct; 40100468e9SJames Morris enum ip_conntrack_info ctinfo; 41100468e9SJames Morris 42587aa641SPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 43587aa641SPatrick McHardy if (ct && !ct->secmark) 44587aa641SPatrick McHardy ct->secmark = skb->secmark; 45100468e9SJames Morris } 46100468e9SJames Morris } 47100468e9SJames Morris 48100468e9SJames Morris /* 49100468e9SJames Morris * If packet has no security mark, and the connection does, restore the 50100468e9SJames Morris * security mark from the connection to the packet. 51100468e9SJames Morris */ 52100468e9SJames Morris static void secmark_restore(struct sk_buff *skb) 53100468e9SJames Morris { 54100468e9SJames Morris if (!skb->secmark) { 55587aa641SPatrick McHardy struct nf_conn *ct; 56100468e9SJames Morris enum ip_conntrack_info ctinfo; 57100468e9SJames Morris 58587aa641SPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 59587aa641SPatrick McHardy if (ct && ct->secmark) 60587aa641SPatrick McHardy skb->secmark = ct->secmark; 61100468e9SJames Morris } 62100468e9SJames Morris } 63100468e9SJames Morris 643db05feaSHerbert Xu static unsigned int target(struct sk_buff *skb, const struct net_device *in, 65100468e9SJames Morris const struct net_device *out, unsigned int hooknum, 66100468e9SJames Morris const struct xt_target *target, 67fe1cb108SPatrick McHardy const void *targinfo) 68100468e9SJames Morris { 69100468e9SJames Morris const struct xt_connsecmark_target_info *info = targinfo; 70100468e9SJames Morris 71100468e9SJames Morris switch (info->mode) { 72100468e9SJames Morris case CONNSECMARK_SAVE: 73100468e9SJames Morris secmark_save(skb); 74100468e9SJames Morris break; 75100468e9SJames Morris 76100468e9SJames Morris case CONNSECMARK_RESTORE: 77100468e9SJames Morris secmark_restore(skb); 78100468e9SJames Morris break; 79100468e9SJames Morris 80100468e9SJames Morris default: 81100468e9SJames Morris BUG(); 82100468e9SJames Morris } 83100468e9SJames Morris 84100468e9SJames Morris return XT_CONTINUE; 85100468e9SJames Morris } 86100468e9SJames Morris 87e1931b78SJan Engelhardt static bool checkentry(const char *tablename, const void *entry, 88100468e9SJames Morris const struct xt_target *target, void *targinfo, 89efa74165SPatrick McHardy unsigned int hook_mask) 90100468e9SJames Morris { 91a47362a2SJan Engelhardt const struct xt_connsecmark_target_info *info = targinfo; 92100468e9SJames Morris 9311078c37SYasuyuki Kozakai if (nf_ct_l3proto_try_module_get(target->family) < 0) { 9411078c37SYasuyuki Kozakai printk(KERN_WARNING "can't load conntrack support for " 9511078c37SYasuyuki Kozakai "proto=%d\n", target->family); 96e1931b78SJan Engelhardt return false; 9711078c37SYasuyuki Kozakai } 98100468e9SJames Morris switch (info->mode) { 99100468e9SJames Morris case CONNSECMARK_SAVE: 100100468e9SJames Morris case CONNSECMARK_RESTORE: 101100468e9SJames Morris break; 102100468e9SJames Morris 103100468e9SJames Morris default: 104100468e9SJames Morris printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); 105e1931b78SJan Engelhardt return false; 106100468e9SJames Morris } 107100468e9SJames Morris 108e1931b78SJan Engelhardt return true; 109100468e9SJames Morris } 110100468e9SJames Morris 11111078c37SYasuyuki Kozakai static void 11211078c37SYasuyuki Kozakai destroy(const struct xt_target *target, void *targinfo) 11311078c37SYasuyuki Kozakai { 11411078c37SYasuyuki Kozakai nf_ct_l3proto_module_put(target->family); 11511078c37SYasuyuki Kozakai } 11611078c37SYasuyuki Kozakai 1179f15c530SPatrick McHardy static struct xt_target xt_connsecmark_target[] __read_mostly = { 1184470bbc7SPatrick McHardy { 119100468e9SJames Morris .name = "CONNSECMARK", 120100468e9SJames Morris .family = AF_INET, 1214470bbc7SPatrick McHardy .checkentry = checkentry, 12211078c37SYasuyuki Kozakai .destroy = destroy, 123100468e9SJames Morris .target = target, 124100468e9SJames Morris .targetsize = sizeof(struct xt_connsecmark_target_info), 125100468e9SJames Morris .table = "mangle", 126100468e9SJames Morris .me = THIS_MODULE, 1274470bbc7SPatrick McHardy }, 1284470bbc7SPatrick McHardy { 1294470bbc7SPatrick McHardy .name = "CONNSECMARK", 130100468e9SJames Morris .family = AF_INET6, 1314470bbc7SPatrick McHardy .checkentry = checkentry, 13211078c37SYasuyuki Kozakai .destroy = destroy, 1334470bbc7SPatrick McHardy .target = target, 1344470bbc7SPatrick McHardy .targetsize = sizeof(struct xt_connsecmark_target_info), 1354470bbc7SPatrick McHardy .table = "mangle", 1364470bbc7SPatrick McHardy .me = THIS_MODULE, 1374470bbc7SPatrick McHardy }, 138100468e9SJames Morris }; 139100468e9SJames Morris 140100468e9SJames Morris static int __init xt_connsecmark_init(void) 141100468e9SJames Morris { 14228094864SThomas Graf return xt_register_targets(xt_connsecmark_target, 14328094864SThomas Graf ARRAY_SIZE(xt_connsecmark_target)); 144100468e9SJames Morris } 145100468e9SJames Morris 146100468e9SJames Morris static void __exit xt_connsecmark_fini(void) 147100468e9SJames Morris { 14828094864SThomas Graf xt_unregister_targets(xt_connsecmark_target, 14928094864SThomas Graf ARRAY_SIZE(xt_connsecmark_target)); 150100468e9SJames Morris } 151100468e9SJames Morris 152100468e9SJames Morris module_init(xt_connsecmark_init); 153100468e9SJames Morris module_exit(xt_connsecmark_fini); 154