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