Files
Tplink-xx230v_kernel/net/ipv4/ecnt_net_ipv4.h

483 lines
11 KiB
C
Executable File

#ifndef _LINUX_ECNT_NET_IPV4_H
#define _LINUX_ECNT_NET_IPV4_H
#include <uapi/linux/in.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/netdevice.h>
#include <linux/icmp.h>
#include <ecnt_hook/ecnt_hook.h>
#include <linux/ecnt_vlan_bind.h>
#include "../ecnt_net.h"
#include <linux/foe_hook.h>
#include "../../include/uapi/linux/ecnt_in.h"
#include <asm/tc3162/tc3162.h>
#if defined(TCSUPPORT_TSO_ENABLE)
#include <ecnt_hook/ecnt_hook_tso.h>
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(4,9,263)
#define IP_CMSG_CUSTOM_DEFINE_START 8
#elif LINUX_VERSION_CODE > KERNEL_VERSION(3,19,8)
#define IP_CMSG_CUSTOM_DEFINE_START 7
#else
#define IP_CMSG_CUSTOM_DEFINE_START 6
#endif
#define IP_CMSG_SKB_MARK BIT(IP_CMSG_CUSTOM_DEFINE_START+1)
#define IP_CMSG_VLAN_ID BIT(IP_CMSG_CUSTOM_DEFINE_START+2)
static inline int ecnt_do_ip_setsockopt_inline_hook
(struct sock *sk, int level, struct inet_sock *inet,
int optname, char __user *optval, unsigned int optlen, int *err)
{
int val = 0;
switch ( optname )
{
case IP_SKB_MARK_FLAG:
case IP_SKB_VLAN_ID_FLAG:
case IP_SKB_MARK:
case IP_SKB_VLAN_ID:
case IP_SKB_PBIT:
if (optlen >= sizeof(int))
{
if (get_user(val, (int __user *) optval))
return ECNT_HOOK_ERROR;
}
else if (optlen >= sizeof(__u16))
{
__u16 u16val;
if (get_user(u16val, (__u16 __user *) optval))
return ECNT_HOOK_ERROR;
val = (int) u16val;
}
else if (optlen >= sizeof(char))
{
unsigned char ucval;
if (get_user(ucval, (unsigned char __user *) optval))
return ECNT_HOOK_ERROR;
val = (int) ucval;
}
break;
default:
break;
}
switch ( optname )
{
case IP_SKB_MARK_FLAG:
if ( val )
inet->cmsg_flags |= IP_CMSG_SKB_MARK;
else
inet->cmsg_flags &= ~IP_CMSG_SKB_MARK;
*err = 0;
break;
case IP_SKB_VLAN_ID_FLAG:
if ( val )
inet->cmsg_flags |= IP_CMSG_VLAN_ID;
else
inet->cmsg_flags &= ~IP_CMSG_VLAN_ID;
*err = 0;
break;
case IP_SKB_MARK:
sk->sk_mark = val;
*err = 0;
break;
case IP_SKB_VLAN_ID:
sk->lVlanId = val;
*err = 0;
break;
case IP_SKB_PBIT:
sk->lPbit = val;
*err = 0;
break;
default:
break;
}
return ECNT_CONTINUE;
}
static inline int ecnt_do_ip_getsockopt_inline_hook
(struct sock *sk, int level, struct inet_sock *inet,
int optname, char __user *optval, int __user *optlen, unsigned int flags)
{
int val = 0, len = 0;
if (get_user(len, optlen))
return ECNT_HOOK_ERROR;
if (len < 0)
return ECNT_HOOK_ERROR;
switch ( optname )
{
case IP_SKB_MARK_FLAG:
val = (inet->cmsg_flags & IP_CMSG_SKB_MARK) != 0;
break;
case IP_SKB_VLAN_ID_FLAG:
val = (inet->cmsg_flags & IP_CMSG_VLAN_ID) != 0;
break;
case IP_SKB_MARK:
val = sk->sk_mark;
break;
case IP_SKB_VLAN_ID:
val = sk->lVlanId;
break;
default:
return ECNT_CONTINUE;
}
if (len < sizeof(u16) && len > 0 && val >= 0 && val <= 255) {
unsigned char ucval = (unsigned char)val;
len = 1;
if (put_user(len, optlen))
return ECNT_HOOK_ERROR;
if (copy_to_user(optval, &ucval, 1))
return ECNT_HOOK_ERROR;
} else {
len = min_t(unsigned int, sizeof(int), len);
if (put_user(len, optlen))
return ECNT_HOOK_ERROR;
if (copy_to_user(optval, &val, len))
return ECNT_HOOK_ERROR;
}
return ECNT_RETURN;
}
static inline void ip_cmsg_recv_skbmark
(struct msghdr *msg, struct sk_buff *skb)
{
__u32 skb_mark = skb->mark;
put_cmsg(msg, SOL_IP, IP_SKB_MARK_FLAG, sizeof(__u32), &skb_mark);
}
static inline void ip_cmsg_recv_vlanid
(struct msghdr *msg, struct sk_buff *skb)
{
#if defined(TCSUPPORT_CT_VLAN_BIND)
__be16 lVlanId = VBIND_INVALID_VLANID;
if (ROUTING_MODE_VLAN_PACKET ==
(skb->vlan_tag_flag & ROUTING_MODE_VLAN_PACKET)
&& (skb->vlan_tags[0] < VBIND_INVALID_VLANID) )
lVlanId = skb->vlan_tags[0];
put_cmsg(msg, SOL_IP, IP_SKB_VLAN_ID_FLAG, sizeof(__u16), &lVlanId);
#endif
}
static inline void ecnt_ip_cmsg_recv_inline_hook
(struct msghdr *msg, struct sk_buff *skb, int flags)
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,8)
if ( flags & IP_CMSG_SKB_MARK )
ip_cmsg_recv_skbmark(msg, skb);
if ( flags & IP_CMSG_VLAN_ID )
ip_cmsg_recv_vlanid(msg, skb);
#else
if ( (flags>>=1) == 0 )
return;
if ( flags & 1 )
ip_cmsg_recv_skbmark(msg, skb);
if ( (flags>>=1) == 0 )
return;
if ( flags & 1 )
ip_cmsg_recv_vlanid(msg, skb);
#endif
return;
}
static inline int ecnt_udp_send_skb_inline_hook
(struct inet_sock *inet, struct sock *sk, struct sk_buff *skb)
{
if ( !inet || !sk || !skb )
return ECNT_CONTINUE;
#if defined(TCSUPPORT_CT_VLAN_BIND)
ecnt_dns_vlanid_store(inet, sk, skb);
#endif
return ECNT_CONTINUE;
}
static inline int ecnt_tcp_recvmsg_inline_hook
(struct sock *sk, struct sk_buff *skb)
{
if ( !sk || !skb )
return ECNT_CONTINUE;
ecnt_skbmark_to_sockmark_copy(sk, skb);
return ECNT_CONTINUE;
}
static inline int ecnt_udp_recvmsg_inline_hook
(struct sock *sk, struct sk_buff *skb)
{
if ( !sk || !skb )
return ECNT_CONTINUE;
ecnt_skbmark_to_sockmark_copy(sk, skb);
return ECNT_CONTINUE;
}
static inline int ecnt_tcp_v4_rcv_inline_hook
(struct sock *sk, struct sk_buff *skb, struct net *net,
struct iphdr *iph, struct tcphdr *th)
{
#if defined(TCSUPPORT_CT)
static uint32_t oldstamp = 0,newstamp = 0;
#endif
if (!sk)
{
#if defined(TCSUPPORT_CT)
if(nf_conntrack_ftp_port == ntohs(th->dest)
&& !strstr(skb->dev->name, "br0")
)
{
newstamp = jiffies;
if(jiffies_to_usecs(newstamp - oldstamp) >= 5*USEC_PER_SEC)
printk(KERN_INFO "TCSysLog FTP service is not open,"
" reject incoming connection from %d.%d.%d.%d\n",
((unsigned char *)&iph->saddr)[0],((unsigned char *)&iph->saddr)[1],
((unsigned char *)&iph->saddr)[2],((unsigned char *)&iph->saddr)[3]);
oldstamp = newstamp;
}
if ( nf_conntrack_portscan_enable )
{
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
return ECNT_RETURN_DROP;
if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb))
{
TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
}
return ECNT_RETURN_DROP;
}
#endif
}
if(ra_sw_nat_local_in_tx)
ra_sw_nat_local_in_tx(skb, ntohs(th->dest));
return ECNT_CONTINUE;
}
static inline int ecnt_udp_v4_rcv_inline_hook
(struct sk_buff *skb, struct udphdr *uh)
{
if (ra_sw_nat_local_in_tx
&& (ECNT_RETURN_DROP == ra_sw_nat_local_in_tx(skb, ntohs(uh->dest))))
{
return ECNT_RETURN_DROP;
}
return ECNT_CONTINUE;
}
static inline int ecnt_icmp_send_inline_hook
(struct sk_buff *skb_in, int type, int code, __be32 info)
{
#if defined(TCSUPPORT_CT)
if ( nf_conntrack_portscan_enable
&& ICMP_DEST_UNREACH == type
&& ICMP_PORT_UNREACH == code )
{
return ECNT_RETURN;
}
#endif
return ECNT_CONTINUE;
}
static inline int ecnt_arp_xmit_inline_hook
(struct sk_buff *skb)
{
#if defined(TCSUPPORT_CT_QOS)
ecnt_set_qoshigh_hook(skb);
#endif
return ECNT_CONTINUE;
}
#if defined(TCSUPPORT_TSO_ENABLE)
/* if match the rule, then set the tso mark. */
static inline int ecnt_tcp_v4_send_check_inline_hook(struct sk_buff *skb,
__be32 saddr, __be32 daddr)
{
tsoRuleEntry_v4_t entry;
struct tcphdr *th;
th = tcp_hdr(skb);
entry.dport = ntohs(th->dest);
entry.sport = ntohs(th->source);
entry.daddr_v4 = daddr;
entry.saddr_v4 = saddr;
if(TSO_SET_SKB_MARK_V4(&entry) == 0){
skb->tso_mark |= TSO_ENABLE_MARK;
}
else{
skb->tso_mark &= (~TSO_ENABLE_MARK);
}
return ECNT_CONTINUE;
}
#endif
static inline void ecnt_ipmr_cache_report_inline_hook(struct sock *sk,
struct sk_buff *skb, struct sk_buff *pkt)
{
skb->dev = pkt->dev;
skb->mark = pkt->mark;
skb->skb_iif = pkt->skb_iif;
ipv4_pktinfo_prepare(sk, skb);
return;
}
#if defined(TCSUPPORT_TEST_SAMBA_SHORTCUT)
extern int SmbdTxSpeedOn;
extern int SmbdTxSpeedCnt0;
static inline int sambaTxShortCut(struct sk_buff *skb)
{
struct iphdr *iph = NULL;
skb->protocol = htons(ETH_P_IP);
/*add layer3 header*/
skb_push(skb, sizeof(struct iphdr));
skb_reset_network_header(skb);
memcpy(skb->data, skb->sk->sk_smbd_info.smbd_ip_header, sizeof(struct iphdr));
iph = ip_hdr(skb);
iph->tot_len = htons(skb->len);
/*add layer2 header*/
skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
memcpy(skb->data, skb->sk->sk_smbd_info.smbd_mac_header, ETH_HLEN);
skb->dev = (struct net_device *)(skb->sk->sk_smbd_info.smbd_outDev);
return dev_queue_xmit(skb);
}
#endif
extern int ShortCutTxSpeedCnt0;
static inline int ecnt_shortcut_tx(struct sk_buff *skb)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,115)
struct iphdr *iph = NULL;
skb->protocol = htons(ETH_P_IP);
/*add layer3 header*/
skb_push(skb, sizeof(struct iphdr));
skb_reset_network_header(skb);
memcpy(skb->data, skb->sk->sk_shortcut_info.ip_header, sizeof(struct iphdr));
iph = ip_hdr(skb);
iph->tot_len = htons(skb->len);
/*add layer2 header*/
skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
memcpy(skb->data, skb->sk->sk_shortcut_info.mac_header, ETH_HLEN);
skb->dev = (struct net_device *)(skb->sk->sk_shortcut_info.out_dev);
/*if is 7526, localout use short cut; if 7528, localout use half hwnat and tso; */
if(isEN751221){
return dev_queue_xmit(skb);
}else
{
ra_sw_nat_hook_set_magic(skb, FOE_MAGIC_APP_SHORTCUT);
ra_sw_nat_hook_sendto_ppe(skb);
return 0;
}
#endif
return 0;
}
static inline int ecnt_tcp_transmit_skb_inline_hook(struct sk_buff *skb)
{
int ret;
#if defined(TCSUPPORT_TSO_ENABLE)
if(skb->tso_mark & TSO_ENABLE_MARK)
{
ret = TSO_SHORTCUT_TO_PPE(skb);
if(ret <= 0)
return ret;
}
#endif
#if defined(TCSUPPORT_TEST_SAMBA_SHORTCUT)
if(SmbdTxSpeedOn && skb->sk && skb->sk->sk_smbd_info.smbd_sk)
{
/* this samba flow has speed up, has learn mac & IP */
if(skb->sk->sk_smbd_info.smbd_speed){
if(skb->sk->sk_smbd_info.smbd_outDev == NULL){
printk("samba tx shortcut: NULL dev \n");
return ECNT_HOOK_ERROR;
}
SmbdTxSpeedCnt0++;
skb->smbd_on_speed = 1;
return sambaTxShortCut(skb);
}else{
skb->smbd_on_speed = 0;
}
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,115)
if(skb->sk && skb->sk->sk_shortcut_info.shortcut_sk)
{
/* this samba flow has speed up, has learn mac & IP */
if(skb->sk->sk_shortcut_info.shortcut_speed && skb->sk->sk_shortcut_info.out_dev)
{
ShortCutTxSpeedCnt0++;
skb->shortcut_on_speed = 1;
return ecnt_shortcut_tx(skb);
}
else
{
skb->shortcut_on_speed = 0;
}
}
#endif
return ECNT_HOOK_ERROR;
}
static inline int ecnt_raw_recvmsg_inline_hook(struct sock *sk, struct sk_buff *skb)
{
#if defined (TCSUPPORT_CT_JOYME4)
if ( sk && skb )
{
if ( sk->lPbit & SOCK_TYPE_COPY_MARK )
{
sk->sk_mark = (skb->mark & 0xfffffffe);
if ( 1 == skb->lan_vlan_tci_valid )
sk->sk_mark |= 0x1;
}
}
#endif
return ECNT_CONTINUE;
}
static inline int ecnt_tcp_close_inline_hook(struct sock *sk)
{
#if defined(TCSUPPORT_TSO_ENABLE)
return TSO_SESSION_DESTROY_V4(sk);
#endif
return 0;
}
#endif