1/* 2 * IPv6 packet mangling table, a port of the IPv4 mangle table to IPv6 3 * 4 * Copyright (C) 2000-2001 by Harald Welte <laforge@gnumonks.org> 5 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11#include <linux/module.h> 12#include <linux/netfilter_ipv6/ip6_tables.h> 13 14MODULE_LICENSE("GPL"); 15MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 16MODULE_DESCRIPTION("ip6tables mangle table"); 17 18#define MANGLE_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | \ 19 (1 << NF_IP6_LOCAL_IN) | \ 20 (1 << NF_IP6_FORWARD) | \ 21 (1 << NF_IP6_LOCAL_OUT) | \ 22 (1 << NF_IP6_POST_ROUTING)) 23 24#define DEBUGP(x, args...) 25 26static struct 27{ 28 struct ip6t_replace repl; 29 struct ip6t_standard entries[5]; 30 struct ip6t_error term; 31} initial_table __initdata = { 32 .repl = { 33 .name = "mangle", 34 .valid_hooks = MANGLE_VALID_HOOKS, 35 .num_entries = 6, 36 .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), 37 .hook_entry = { 38 [NF_IP6_PRE_ROUTING] = 0, 39 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), 40 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, 41 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, 42 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, 43 }, 44 .underflow = { 45 [NF_IP6_PRE_ROUTING] = 0, 46 [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard), 47 [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2, 48 [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, 49 [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, 50 }, 51 }, 52 .entries = { 53 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ 54 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ 55 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ 56 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ 57 IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ 58 }, 59 .term = IP6T_ERROR_INIT, /* ERROR */ 60}; 61 62static struct xt_table packet_mangler = { 63 .name = "mangle", 64 .valid_hooks = MANGLE_VALID_HOOKS, 65 .lock = RW_LOCK_UNLOCKED, 66 .me = THIS_MODULE, 67 .af = AF_INET6, 68}; 69 70/* The work comes in here from netfilter.c. */ 71static unsigned int 72ip6t_route_hook(unsigned int hook, 73 struct sk_buff **pskb, 74 const struct net_device *in, 75 const struct net_device *out, 76 int (*okfn)(struct sk_buff *)) 77{ 78 return ip6t_do_table(pskb, hook, in, out, &packet_mangler); 79} 80 81static unsigned int 82ip6t_local_hook(unsigned int hook, 83 struct sk_buff **pskb, 84 const struct net_device *in, 85 const struct net_device *out, 86 int (*okfn)(struct sk_buff *)) 87{ 88 89 unsigned int ret; 90 struct in6_addr saddr, daddr; 91 u_int8_t hop_limit; 92 u_int32_t flowlabel, mark; 93 94 95 /* save source/dest address, mark, hoplimit, flowlabel, priority, */ 96 memcpy(&saddr, &ipv6_hdr(*pskb)->saddr, sizeof(saddr)); 97 memcpy(&daddr, &ipv6_hdr(*pskb)->daddr, sizeof(daddr)); 98 mark = (*pskb)->mark; 99 hop_limit = ipv6_hdr(*pskb)->hop_limit; 100 101 /* flowlabel and prio (includes version, which shouldn't change either */ 102 flowlabel = *((u_int32_t *)ipv6_hdr(*pskb)); 103 104 ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); 105 106 if (ret != NF_DROP && ret != NF_STOLEN 107 && (memcmp(&ipv6_hdr(*pskb)->saddr, &saddr, sizeof(saddr)) 108 || memcmp(&ipv6_hdr(*pskb)->daddr, &daddr, sizeof(daddr)) 109 || (*pskb)->mark != mark 110 || ipv6_hdr(*pskb)->hop_limit != hop_limit)) 111 return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; 112 113 return ret; 114} 115 116static struct nf_hook_ops ip6t_ops[] = { 117 { 118 .hook = ip6t_route_hook, 119 .owner = THIS_MODULE, 120 .pf = PF_INET6, 121 .hooknum = NF_IP6_PRE_ROUTING, 122 .priority = NF_IP6_PRI_MANGLE, 123 }, 124 { 125 .hook = ip6t_local_hook, 126 .owner = THIS_MODULE, 127 .pf = PF_INET6, 128 .hooknum = NF_IP6_LOCAL_IN, 129 .priority = NF_IP6_PRI_MANGLE, 130 }, 131 { 132 .hook = ip6t_route_hook, 133 .owner = THIS_MODULE, 134 .pf = PF_INET6, 135 .hooknum = NF_IP6_FORWARD, 136 .priority = NF_IP6_PRI_MANGLE, 137 }, 138 { 139 .hook = ip6t_local_hook, 140 .owner = THIS_MODULE, 141 .pf = PF_INET6, 142 .hooknum = NF_IP6_LOCAL_OUT, 143 .priority = NF_IP6_PRI_MANGLE, 144 }, 145 { 146 .hook = ip6t_route_hook, 147 .owner = THIS_MODULE, 148 .pf = PF_INET6, 149 .hooknum = NF_IP6_POST_ROUTING, 150 .priority = NF_IP6_PRI_MANGLE, 151 }, 152}; 153 154static int __init ip6table_mangle_init(void) 155{ 156 int ret; 157 158 /* Register table */ 159 ret = ip6t_register_table(&packet_mangler, &initial_table.repl); 160 if (ret < 0) 161 return ret; 162 163 /* Register hooks */ 164 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 165 if (ret < 0) 166 goto cleanup_table; 167 168 return ret; 169 170 cleanup_table: 171 ip6t_unregister_table(&packet_mangler); 172 return ret; 173} 174 175static void __exit ip6table_mangle_fini(void) 176{ 177 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 178 ip6t_unregister_table(&packet_mangler); 179} 180 181module_init(ip6table_mangle_init); 182module_exit(ip6table_mangle_fini); 183