ip6t_REJECT.c (3224B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IP6 tables REJECT target module 4 * Linux INET6 implementation 5 * 6 * Copyright (C)2003 USAGI/WIDE Project 7 * 8 * Authors: 9 * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> 10 * 11 * Copyright (c) 2005-2007 Patrick McHardy <kaber@trash.net> 12 * 13 * Based on net/ipv4/netfilter/ipt_REJECT.c 14 */ 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 17#include <linux/gfp.h> 18#include <linux/module.h> 19#include <linux/skbuff.h> 20#include <linux/icmpv6.h> 21#include <linux/netdevice.h> 22#include <net/icmp.h> 23#include <net/flow.h> 24#include <linux/netfilter/x_tables.h> 25#include <linux/netfilter_ipv6/ip6_tables.h> 26#include <linux/netfilter_ipv6/ip6t_REJECT.h> 27 28#include <net/netfilter/ipv6/nf_reject.h> 29 30MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>"); 31MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6"); 32MODULE_LICENSE("GPL"); 33 34static unsigned int 35reject_tg6(struct sk_buff *skb, const struct xt_action_param *par) 36{ 37 const struct ip6t_reject_info *reject = par->targinfo; 38 struct net *net = xt_net(par); 39 40 switch (reject->with) { 41 case IP6T_ICMP6_NO_ROUTE: 42 nf_send_unreach6(net, skb, ICMPV6_NOROUTE, xt_hooknum(par)); 43 break; 44 case IP6T_ICMP6_ADM_PROHIBITED: 45 nf_send_unreach6(net, skb, ICMPV6_ADM_PROHIBITED, 46 xt_hooknum(par)); 47 break; 48 case IP6T_ICMP6_NOT_NEIGHBOUR: 49 nf_send_unreach6(net, skb, ICMPV6_NOT_NEIGHBOUR, 50 xt_hooknum(par)); 51 break; 52 case IP6T_ICMP6_ADDR_UNREACH: 53 nf_send_unreach6(net, skb, ICMPV6_ADDR_UNREACH, 54 xt_hooknum(par)); 55 break; 56 case IP6T_ICMP6_PORT_UNREACH: 57 nf_send_unreach6(net, skb, ICMPV6_PORT_UNREACH, 58 xt_hooknum(par)); 59 break; 60 case IP6T_ICMP6_ECHOREPLY: 61 /* Do nothing */ 62 break; 63 case IP6T_TCP_RESET: 64 nf_send_reset6(net, par->state->sk, skb, xt_hooknum(par)); 65 break; 66 case IP6T_ICMP6_POLICY_FAIL: 67 nf_send_unreach6(net, skb, ICMPV6_POLICY_FAIL, xt_hooknum(par)); 68 break; 69 case IP6T_ICMP6_REJECT_ROUTE: 70 nf_send_unreach6(net, skb, ICMPV6_REJECT_ROUTE, 71 xt_hooknum(par)); 72 break; 73 } 74 75 return NF_DROP; 76} 77 78static int reject_tg6_check(const struct xt_tgchk_param *par) 79{ 80 const struct ip6t_reject_info *rejinfo = par->targinfo; 81 const struct ip6t_entry *e = par->entryinfo; 82 83 if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { 84 pr_info_ratelimited("ECHOREPLY is not supported\n"); 85 return -EINVAL; 86 } else if (rejinfo->with == IP6T_TCP_RESET) { 87 /* Must specify that it's a TCP packet */ 88 if (!(e->ipv6.flags & IP6T_F_PROTO) || 89 e->ipv6.proto != IPPROTO_TCP || 90 (e->ipv6.invflags & XT_INV_PROTO)) { 91 pr_info_ratelimited("TCP_RESET illegal for non-tcp\n"); 92 return -EINVAL; 93 } 94 } 95 return 0; 96} 97 98static struct xt_target reject_tg6_reg __read_mostly = { 99 .name = "REJECT", 100 .family = NFPROTO_IPV6, 101 .target = reject_tg6, 102 .targetsize = sizeof(struct ip6t_reject_info), 103 .table = "filter", 104 .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) | 105 (1 << NF_INET_LOCAL_OUT), 106 .checkentry = reject_tg6_check, 107 .me = THIS_MODULE 108}; 109 110static int __init reject_tg6_init(void) 111{ 112 return xt_register_target(&reject_tg6_reg); 113} 114 115static void __exit reject_tg6_exit(void) 116{ 117 xt_unregister_target(&reject_tg6_reg); 118} 119 120module_init(reject_tg6_init); 121module_exit(reject_tg6_exit);