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 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 #include <linux/module.h> 19 #include <linux/skbuff.h> 20 #include <linux/netfilter/x_tables.h> 21 #include <linux/netfilter/xt_CONNSECMARK.h> 22 #include <net/netfilter/nf_conntrack_compat.h> 23 24 #define PFX "CONNSECMARK: " 25 26 MODULE_LICENSE("GPL"); 27 MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); 28 MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module"); 29 MODULE_ALIAS("ipt_CONNSECMARK"); 30 MODULE_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 */ 36 static void secmark_save(struct sk_buff *skb) 37 { 38 if (skb->secmark) { 39 u32 *connsecmark; 40 enum ip_conntrack_info ctinfo; 41 42 connsecmark = nf_ct_get_secmark(skb, &ctinfo); 43 if (connsecmark && !*connsecmark) 44 if (*connsecmark != skb->secmark) 45 *connsecmark = skb->secmark; 46 } 47 } 48 49 /* 50 * If packet has no security mark, and the connection does, restore the 51 * security mark from the connection to the packet. 52 */ 53 static void secmark_restore(struct sk_buff *skb) 54 { 55 if (!skb->secmark) { 56 u32 *connsecmark; 57 enum ip_conntrack_info ctinfo; 58 59 connsecmark = nf_ct_get_secmark(skb, &ctinfo); 60 if (connsecmark && *connsecmark) 61 if (skb->secmark != *connsecmark) 62 skb->secmark = *connsecmark; 63 } 64 } 65 66 static unsigned int target(struct sk_buff **pskb, const struct net_device *in, 67 const struct net_device *out, unsigned int hooknum, 68 const struct xt_target *target, 69 const void *targinfo) 70 { 71 struct sk_buff *skb = *pskb; 72 const struct xt_connsecmark_target_info *info = targinfo; 73 74 switch (info->mode) { 75 case CONNSECMARK_SAVE: 76 secmark_save(skb); 77 break; 78 79 case CONNSECMARK_RESTORE: 80 secmark_restore(skb); 81 break; 82 83 default: 84 BUG(); 85 } 86 87 return XT_CONTINUE; 88 } 89 90 static int checkentry(const char *tablename, const void *entry, 91 const struct xt_target *target, void *targinfo, 92 unsigned int hook_mask) 93 { 94 struct xt_connsecmark_target_info *info = targinfo; 95 96 switch (info->mode) { 97 case CONNSECMARK_SAVE: 98 case CONNSECMARK_RESTORE: 99 break; 100 101 default: 102 printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); 103 return 0; 104 } 105 106 return 1; 107 } 108 109 static struct xt_target xt_connsecmark_target[] = { 110 { 111 .name = "CONNSECMARK", 112 .family = AF_INET, 113 .checkentry = checkentry, 114 .target = target, 115 .targetsize = sizeof(struct xt_connsecmark_target_info), 116 .table = "mangle", 117 .me = THIS_MODULE, 118 }, 119 { 120 .name = "CONNSECMARK", 121 .family = AF_INET6, 122 .checkentry = checkentry, 123 .target = target, 124 .targetsize = sizeof(struct xt_connsecmark_target_info), 125 .table = "mangle", 126 .me = THIS_MODULE, 127 }, 128 }; 129 130 static int __init xt_connsecmark_init(void) 131 { 132 need_conntrack(); 133 return xt_register_targets(xt_connsecmark_target, 134 ARRAY_SIZE(xt_connsecmark_target)); 135 } 136 137 static void __exit xt_connsecmark_fini(void) 138 { 139 xt_unregister_targets(xt_connsecmark_target, 140 ARRAY_SIZE(xt_connsecmark_target)); 141 } 142 143 module_init(xt_connsecmark_init); 144 module_exit(xt_connsecmark_fini); 145