nft_chain_route_ipv4.c revision 9370761c56b66aa5c65e069a7b010111a025018d
1/* 2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net> 3 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10#include <linux/module.h> 11#include <linux/init.h> 12#include <linux/list.h> 13#include <linux/skbuff.h> 14#include <linux/netlink.h> 15#include <linux/netfilter.h> 16#include <linux/netfilter_ipv4.h> 17#include <linux/netfilter/nfnetlink.h> 18#include <linux/netfilter/nf_tables.h> 19#include <net/netfilter/nf_tables.h> 20#include <net/route.h> 21#include <net/ip.h> 22 23static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, 24 struct sk_buff *skb, 25 const struct net_device *in, 26 const struct net_device *out, 27 int (*okfn)(struct sk_buff *)) 28{ 29 unsigned int ret; 30 u32 mark; 31 __be32 saddr, daddr; 32 u_int8_t tos; 33 const struct iphdr *iph; 34 35 /* root is playing with raw sockets. */ 36 if (skb->len < sizeof(struct iphdr) || 37 ip_hdrlen(skb) < sizeof(struct iphdr)) 38 return NF_ACCEPT; 39 40 mark = skb->mark; 41 iph = ip_hdr(skb); 42 saddr = iph->saddr; 43 daddr = iph->daddr; 44 tos = iph->tos; 45 46 ret = nft_do_chain(ops, skb, in, out, okfn); 47 if (ret != NF_DROP && ret != NF_QUEUE) { 48 iph = ip_hdr(skb); 49 50 if (iph->saddr != saddr || 51 iph->daddr != daddr || 52 skb->mark != mark || 53 iph->tos != tos) 54 if (ip_route_me_harder(skb, RTN_UNSPEC)) 55 ret = NF_DROP; 56 } 57 return ret; 58} 59 60static struct nf_chain_type nft_chain_route_ipv4 = { 61 .family = NFPROTO_IPV4, 62 .name = "route", 63 .type = NFT_CHAIN_T_ROUTE, 64 .hook_mask = (1 << NF_INET_LOCAL_OUT), 65 .fn = { 66 [NF_INET_LOCAL_OUT] = nf_route_table_hook, 67 }, 68 .me = THIS_MODULE, 69}; 70 71static int __init nft_chain_route_init(void) 72{ 73 return nft_register_chain_type(&nft_chain_route_ipv4); 74} 75 76static void __exit nft_chain_route_exit(void) 77{ 78 nft_unregister_chain_type(&nft_chain_route_ipv4); 79} 80 81module_init(nft_chain_route_init); 82module_exit(nft_chain_route_exit); 83 84MODULE_LICENSE("GPL"); 85MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 86MODULE_ALIAS_NFT_CHAIN(AF_INET, "route"); 87