nft_chain_route_ipv4.c revision 0ca743a5599199152a31a7146b83213c786c2eb2
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/netfilter/nf_tables_ipv4.h> 21#include <net/route.h> 22#include <net/ip.h> 23 24static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops, 25 struct sk_buff *skb, 26 const struct net_device *in, 27 const struct net_device *out, 28 int (*okfn)(struct sk_buff *)) 29{ 30 unsigned int ret; 31 struct nft_pktinfo pkt; 32 u32 mark; 33 __be32 saddr, daddr; 34 u_int8_t tos; 35 const struct iphdr *iph; 36 37 /* root is playing with raw sockets. */ 38 if (skb->len < sizeof(struct iphdr) || 39 ip_hdrlen(skb) < sizeof(struct iphdr)) 40 return NF_ACCEPT; 41 42 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out); 43 44 mark = skb->mark; 45 iph = ip_hdr(skb); 46 saddr = iph->saddr; 47 daddr = iph->daddr; 48 tos = iph->tos; 49 50 ret = nft_do_chain_pktinfo(&pkt, ops); 51 if (ret != NF_DROP && ret != NF_QUEUE) { 52 iph = ip_hdr(skb); 53 54 if (iph->saddr != saddr || 55 iph->daddr != daddr || 56 skb->mark != mark || 57 iph->tos != tos) 58 if (ip_route_me_harder(skb, RTN_UNSPEC)) 59 ret = NF_DROP; 60 } 61 return ret; 62} 63 64static struct nf_chain_type nft_chain_route_ipv4 = { 65 .family = NFPROTO_IPV4, 66 .name = "route", 67 .type = NFT_CHAIN_T_ROUTE, 68 .hook_mask = (1 << NF_INET_LOCAL_OUT), 69 .fn = { 70 [NF_INET_LOCAL_OUT] = nf_route_table_hook, 71 }, 72 .me = THIS_MODULE, 73}; 74 75static int __init nft_chain_route_init(void) 76{ 77 return nft_register_chain_type(&nft_chain_route_ipv4); 78} 79 80static void __exit nft_chain_route_exit(void) 81{ 82 nft_unregister_chain_type(&nft_chain_route_ipv4); 83} 84 85module_init(nft_chain_route_init); 86module_exit(nft_chain_route_exit); 87 88MODULE_LICENSE("GPL"); 89MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 90MODULE_ALIAS_NFT_CHAIN(AF_INET, "route"); 91