1e281b19897dc21c1071802808d461627d747a877Jan Engelhardt/* 2e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * "TEE" target extension for Xtables 3e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * Copyright © Sebastian Claßen, 2007 4e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * Jan Engelhardt, 2007-2010 5e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * 6e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * based on ipt_ROUTE.c from Cédric de Launois 7e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * <delaunois@info.ucl.be> 8e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * 9e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * This program is free software; you can redistribute it and/or 10e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * modify it under the terms of the GNU General Public License 11e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * version 2 or later, as published by the Free Software Foundation. 12e281b19897dc21c1071802808d461627d747a877Jan Engelhardt */ 13e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <linux/ip.h> 14e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <linux/module.h> 15cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt#include <linux/percpu.h> 16e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <linux/route.h> 17e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <linux/skbuff.h> 1822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy#include <linux/notifier.h> 19e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <net/checksum.h> 20e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <net/icmp.h> 21e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <net/ip.h> 22e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <net/ipv6.h> 23e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <net/ip6_route.h> 24e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <net/route.h> 25e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <linux/netfilter/x_tables.h> 26e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#include <linux/netfilter/xt_TEE.h> 27e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 28c0cd115667bcd23c2a31fe2114beaab3608de68cIgor Maravić#if IS_ENABLED(CONFIG_NF_CONNTRACK) 29e281b19897dc21c1071802808d461627d747a877Jan Engelhardt# define WITH_CONNTRACK 1 30e281b19897dc21c1071802808d461627d747a877Jan Engelhardt# include <net/netfilter/nf_conntrack.h> 31e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#endif 32e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 3322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardystruct xt_tee_priv { 3422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy struct notifier_block notifier; 3522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy struct xt_tee_tginfo *tginfo; 3622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy int oif; 3722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy}; 3822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 39e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic const union nf_inet_addr tee_zero_address; 40cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardtstatic DEFINE_PER_CPU(bool, tee_active); 41e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 42e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic struct net *pick_net(struct sk_buff *skb) 43e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 44e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#ifdef CONFIG_NET_NS 45e281b19897dc21c1071802808d461627d747a877Jan Engelhardt const struct dst_entry *dst; 46e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 47e281b19897dc21c1071802808d461627d747a877Jan Engelhardt if (skb->dev != NULL) 48e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return dev_net(skb->dev); 49e281b19897dc21c1071802808d461627d747a877Jan Engelhardt dst = skb_dst(skb); 50e281b19897dc21c1071802808d461627d747a877Jan Engelhardt if (dst != NULL && dst->dev != NULL) 51e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return dev_net(dst->dev); 52e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#endif 53e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return &init_net; 54e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 55e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 56e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic bool 57e281b19897dc21c1071802808d461627d747a877Jan Engelhardttee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) 58e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 59e281b19897dc21c1071802808d461627d747a877Jan Engelhardt const struct iphdr *iph = ip_hdr(skb); 60e281b19897dc21c1071802808d461627d747a877Jan Engelhardt struct net *net = pick_net(skb); 61e281b19897dc21c1071802808d461627d747a877Jan Engelhardt struct rtable *rt; 629d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller struct flowi4 fl4; 63e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 649d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller memset(&fl4, 0, sizeof(fl4)); 6522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->priv) { 6622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->priv->oif == -1) 6722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return false; 689d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller fl4.flowi4_oif = info->priv->oif; 6922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy } 709d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller fl4.daddr = info->gw.ip; 719d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller fl4.flowi4_tos = RT_TOS(iph->tos); 729d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller fl4.flowi4_scope = RT_SCOPE_UNIVERSE; 732ad5b9e4bd314fc685086b99e90e5de3bc59e26bEric Dumazet fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; 749d6ec938019c6b16cb9ec96598ebe8f20de435feDavid S. Miller rt = ip_route_output_key(net, &fl4); 75b23dd4fe42b455af5c6e20966b7d6959fa8352eaDavid S. Miller if (IS_ERR(rt)) 76e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return false; 77e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 7850636af715ac1ceb1872bd29a4bdcc68975c3263Eric Dumazet skb_dst_drop(skb); 79d8d1f30b95a635dbd610dcc5eb641aca8f4768cfChangli Gao skb_dst_set(skb, &rt->dst); 80d8d1f30b95a635dbd610dcc5eb641aca8f4768cfChangli Gao skb->dev = rt->dst.dev; 81e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb->protocol = htons(ETH_P_IP); 82e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return true; 83e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 84e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 85e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic unsigned int 864b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardttee_tg4(struct sk_buff *skb, const struct xt_action_param *par) 87e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 88e281b19897dc21c1071802808d461627d747a877Jan Engelhardt const struct xt_tee_tginfo *info = par->targinfo; 89e281b19897dc21c1071802808d461627d747a877Jan Engelhardt struct iphdr *iph; 90e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 9119e8d69c543f8f62050099892b138e981db952ccAlex Shi if (__this_cpu_read(tee_active)) 92cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt return XT_CONTINUE; 93e281b19897dc21c1071802808d461627d747a877Jan Engelhardt /* 94e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * Copy the skb, and route the copy. Will later return %XT_CONTINUE for 95e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * the original skb, which should continue on its way as if nothing has 96e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * happened. The copy should be independently delivered to the TEE 97e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * --gateway. 98e281b19897dc21c1071802808d461627d747a877Jan Engelhardt */ 99e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb = pskb_copy(skb, GFP_ATOMIC); 100e281b19897dc21c1071802808d461627d747a877Jan Engelhardt if (skb == NULL) 101e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return XT_CONTINUE; 102e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 103e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#ifdef WITH_CONNTRACK 104e281b19897dc21c1071802808d461627d747a877Jan Engelhardt /* Avoid counting cloned packets towards the original connection. */ 105e281b19897dc21c1071802808d461627d747a877Jan Engelhardt nf_conntrack_put(skb->nfct); 1065bfddbd46a95c978f4d3c992339cbdf4f4b790a3Eric Dumazet skb->nfct = &nf_ct_untracked_get()->ct_general; 107e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb->nfctinfo = IP_CT_NEW; 108e281b19897dc21c1071802808d461627d747a877Jan Engelhardt nf_conntrack_get(skb->nfct); 109e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#endif 110e281b19897dc21c1071802808d461627d747a877Jan Engelhardt /* 111e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * If we are in PREROUTING/INPUT, the checksum must be recalculated 112e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * since the length could have changed as a result of defragmentation. 113e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * 114e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * We also decrease the TTL to mitigate potential TEE loops 115e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * between two hosts. 116e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * 117e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * Set %IP_DF so that the original source is notified of a potentially 118e281b19897dc21c1071802808d461627d747a877Jan Engelhardt * decreased MTU on the clone route. IPv6 does this too. 119e281b19897dc21c1071802808d461627d747a877Jan Engelhardt */ 120e281b19897dc21c1071802808d461627d747a877Jan Engelhardt iph = ip_hdr(skb); 121e281b19897dc21c1071802808d461627d747a877Jan Engelhardt iph->frag_off |= htons(IP_DF); 122e281b19897dc21c1071802808d461627d747a877Jan Engelhardt if (par->hooknum == NF_INET_PRE_ROUTING || 123e281b19897dc21c1071802808d461627d747a877Jan Engelhardt par->hooknum == NF_INET_LOCAL_IN) 124e281b19897dc21c1071802808d461627d747a877Jan Engelhardt --iph->ttl; 125e281b19897dc21c1071802808d461627d747a877Jan Engelhardt ip_send_check(iph); 126e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 127cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt if (tee_tg_route4(skb, info)) { 12819e8d69c543f8f62050099892b138e981db952ccAlex Shi __this_cpu_write(tee_active, true); 129cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt ip_local_out(skb); 13019e8d69c543f8f62050099892b138e981db952ccAlex Shi __this_cpu_write(tee_active, false); 131cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt } else { 132e281b19897dc21c1071802808d461627d747a877Jan Engelhardt kfree_skb(skb); 133cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt } 134e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return XT_CONTINUE; 135e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 136e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 137dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#if IS_ENABLED(CONFIG_IPV6) 138e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic bool 139e281b19897dc21c1071802808d461627d747a877Jan Engelhardttee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info) 140e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 141e281b19897dc21c1071802808d461627d747a877Jan Engelhardt const struct ipv6hdr *iph = ipv6_hdr(skb); 142e281b19897dc21c1071802808d461627d747a877Jan Engelhardt struct net *net = pick_net(skb); 143e281b19897dc21c1071802808d461627d747a877Jan Engelhardt struct dst_entry *dst; 1444c9483b2fb5d2548c3cc1fe03cdd4484ceeb5d1cDavid S. Miller struct flowi6 fl6; 145e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 1464c9483b2fb5d2548c3cc1fe03cdd4484ceeb5d1cDavid S. Miller memset(&fl6, 0, sizeof(fl6)); 14722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->priv) { 14822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->priv->oif == -1) 14922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return false; 1504c9483b2fb5d2548c3cc1fe03cdd4484ceeb5d1cDavid S. Miller fl6.flowi6_oif = info->priv->oif; 15122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy } 1524c9483b2fb5d2548c3cc1fe03cdd4484ceeb5d1cDavid S. Miller fl6.daddr = info->gw.in6; 1534c9483b2fb5d2548c3cc1fe03cdd4484ceeb5d1cDavid S. Miller fl6.flowlabel = ((iph->flow_lbl[0] & 0xF) << 16) | 1545811662b15db018c740c57d037523683fd3e6123Changli Gao (iph->flow_lbl[1] << 8) | iph->flow_lbl[2]; 1554c9483b2fb5d2548c3cc1fe03cdd4484ceeb5d1cDavid S. Miller dst = ip6_route_output(net, NULL, &fl6); 1565d38b1f8cf8798d4df7809b3f3e38fad4d923e85RongQing.Li if (dst->error) { 1575d38b1f8cf8798d4df7809b3f3e38fad4d923e85RongQing.Li dst_release(dst); 158e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return false; 1595d38b1f8cf8798d4df7809b3f3e38fad4d923e85RongQing.Li } 16050636af715ac1ceb1872bd29a4bdcc68975c3263Eric Dumazet skb_dst_drop(skb); 161e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb_dst_set(skb, dst); 162e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb->dev = dst->dev; 163e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb->protocol = htons(ETH_P_IPV6); 164e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return true; 165e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 166e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 167e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic unsigned int 1684b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardttee_tg6(struct sk_buff *skb, const struct xt_action_param *par) 169e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 170e281b19897dc21c1071802808d461627d747a877Jan Engelhardt const struct xt_tee_tginfo *info = par->targinfo; 171e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 17219e8d69c543f8f62050099892b138e981db952ccAlex Shi if (__this_cpu_read(tee_active)) 173cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt return XT_CONTINUE; 174e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb = pskb_copy(skb, GFP_ATOMIC); 175e281b19897dc21c1071802808d461627d747a877Jan Engelhardt if (skb == NULL) 176e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return XT_CONTINUE; 177e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 178e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#ifdef WITH_CONNTRACK 179e281b19897dc21c1071802808d461627d747a877Jan Engelhardt nf_conntrack_put(skb->nfct); 1805bfddbd46a95c978f4d3c992339cbdf4f4b790a3Eric Dumazet skb->nfct = &nf_ct_untracked_get()->ct_general; 181e281b19897dc21c1071802808d461627d747a877Jan Engelhardt skb->nfctinfo = IP_CT_NEW; 182e281b19897dc21c1071802808d461627d747a877Jan Engelhardt nf_conntrack_get(skb->nfct); 183e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#endif 184e281b19897dc21c1071802808d461627d747a877Jan Engelhardt if (par->hooknum == NF_INET_PRE_ROUTING || 185e281b19897dc21c1071802808d461627d747a877Jan Engelhardt par->hooknum == NF_INET_LOCAL_IN) { 186e281b19897dc21c1071802808d461627d747a877Jan Engelhardt struct ipv6hdr *iph = ipv6_hdr(skb); 187e281b19897dc21c1071802808d461627d747a877Jan Engelhardt --iph->hop_limit; 188e281b19897dc21c1071802808d461627d747a877Jan Engelhardt } 189cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt if (tee_tg_route6(skb, info)) { 19019e8d69c543f8f62050099892b138e981db952ccAlex Shi __this_cpu_write(tee_active, true); 191cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt ip6_local_out(skb); 19219e8d69c543f8f62050099892b138e981db952ccAlex Shi __this_cpu_write(tee_active, false); 193cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt } else { 194e281b19897dc21c1071802808d461627d747a877Jan Engelhardt kfree_skb(skb); 195cd58bcd9787ef4c16ab6e442c4f1bf3539b3ab39Jan Engelhardt } 196e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return XT_CONTINUE; 197e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 198dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#endif 199e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 20022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardystatic int tee_netdev_event(struct notifier_block *this, unsigned long event, 20122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy void *ptr) 20222265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy{ 203351638e7deeed2ec8ce451b53d33921b3da68f83Jiri Pirko struct net_device *dev = netdev_notifier_info_to_dev(ptr); 20422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy struct xt_tee_priv *priv; 20522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 20622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv = container_of(this, struct xt_tee_priv, notifier); 20722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy switch (event) { 20822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy case NETDEV_REGISTER: 20922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (!strcmp(dev->name, priv->tginfo->oif)) 21022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->oif = dev->ifindex; 21122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy break; 21222265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy case NETDEV_UNREGISTER: 21322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (dev->ifindex == priv->oif) 21422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->oif = -1; 21522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy break; 21622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy case NETDEV_CHANGENAME: 21722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (!strcmp(dev->name, priv->tginfo->oif)) 21822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->oif = dev->ifindex; 21922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy else if (dev->ifindex == priv->oif) 22022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->oif = -1; 22122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy break; 22222265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy } 22322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 22422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return NOTIFY_DONE; 22522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy} 22622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 227e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic int tee_tg_check(const struct xt_tgchk_param *par) 228e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 22922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy struct xt_tee_tginfo *info = par->targinfo; 23022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy struct xt_tee_priv *priv; 231e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 232e281b19897dc21c1071802808d461627d747a877Jan Engelhardt /* 0.0.0.0 and :: not allowed */ 23322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (memcmp(&info->gw, &tee_zero_address, 23422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy sizeof(tee_zero_address)) == 0) 23522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return -EINVAL; 23622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 23722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->oif[0]) { 23822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->oif[sizeof(info->oif)-1] != '\0') 23922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return -EINVAL; 24022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 24122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv = kzalloc(sizeof(*priv), GFP_KERNEL); 24222265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (priv == NULL) 24322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return -ENOMEM; 24422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 24522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->tginfo = info; 24622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->oif = -1; 24722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy priv->notifier.notifier_call = tee_netdev_event; 24822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy info->priv = priv; 24922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 25022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy register_netdevice_notifier(&priv->notifier); 25122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy } else 25222265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy info->priv = NULL; 25322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 25422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy return 0; 25522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy} 25622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 25722265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardystatic void tee_tg_destroy(const struct xt_tgdtor_param *par) 25822265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy{ 25922265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy struct xt_tee_tginfo *info = par->targinfo; 26022265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy 26122265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy if (info->priv) { 26222265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy unregister_netdevice_notifier(&info->priv->notifier); 26322265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy kfree(info->priv); 26422265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy } 265e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 266e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 267e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic struct xt_target tee_tg_reg[] __read_mostly = { 268e281b19897dc21c1071802808d461627d747a877Jan Engelhardt { 269e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .name = "TEE", 270e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .revision = 1, 271e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .family = NFPROTO_IPV4, 272e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .target = tee_tg4, 273e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .targetsize = sizeof(struct xt_tee_tginfo), 274e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .checkentry = tee_tg_check, 27522265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy .destroy = tee_tg_destroy, 276e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .me = THIS_MODULE, 277e281b19897dc21c1071802808d461627d747a877Jan Engelhardt }, 278dfd56b8b38fff3586f36232db58e1e9f7885a605Eric Dumazet#if IS_ENABLED(CONFIG_IPV6) 279e281b19897dc21c1071802808d461627d747a877Jan Engelhardt { 280e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .name = "TEE", 281e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .revision = 1, 282e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .family = NFPROTO_IPV6, 283e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .target = tee_tg6, 284e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .targetsize = sizeof(struct xt_tee_tginfo), 285e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .checkentry = tee_tg_check, 28622265a5c3c103cf8c50be62e6c90d045eb649e6dPatrick McHardy .destroy = tee_tg_destroy, 287e281b19897dc21c1071802808d461627d747a877Jan Engelhardt .me = THIS_MODULE, 288e281b19897dc21c1071802808d461627d747a877Jan Engelhardt }, 289e281b19897dc21c1071802808d461627d747a877Jan Engelhardt#endif 290e281b19897dc21c1071802808d461627d747a877Jan Engelhardt}; 291e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 292e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic int __init tee_tg_init(void) 293e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 294e281b19897dc21c1071802808d461627d747a877Jan Engelhardt return xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); 295e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 296e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 297e281b19897dc21c1071802808d461627d747a877Jan Engelhardtstatic void __exit tee_tg_exit(void) 298e281b19897dc21c1071802808d461627d747a877Jan Engelhardt{ 299e281b19897dc21c1071802808d461627d747a877Jan Engelhardt xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); 300e281b19897dc21c1071802808d461627d747a877Jan Engelhardt} 301e281b19897dc21c1071802808d461627d747a877Jan Engelhardt 302e281b19897dc21c1071802808d461627d747a877Jan Engelhardtmodule_init(tee_tg_init); 303e281b19897dc21c1071802808d461627d747a877Jan Engelhardtmodule_exit(tee_tg_exit); 304e281b19897dc21c1071802808d461627d747a877Jan EngelhardtMODULE_AUTHOR("Sebastian Claßen <sebastian.classen@freenet.ag>"); 305e281b19897dc21c1071802808d461627d747a877Jan EngelhardtMODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); 306e281b19897dc21c1071802808d461627d747a877Jan EngelhardtMODULE_DESCRIPTION("Xtables: Reroute packet copy"); 307e281b19897dc21c1071802808d461627d747a877Jan EngelhardtMODULE_LICENSE("GPL"); 308e281b19897dc21c1071802808d461627d747a877Jan EngelhardtMODULE_ALIAS("ipt_TEE"); 309e281b19897dc21c1071802808d461627d747a877Jan EngelhardtMODULE_ALIAS("ip6t_TEE"); 310