/*************************************************************************** * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * All rights reserved. * * $Id: ip_nat.h,v 1.1 2010/05/05 19:34:23 ***************************************************************************/ #ifndef __LWIP_NAT_H__ #define __LWIP_NAT_H__ #include "err.h" #include "opt.h" #include "sys_arch.h" #include "ip_addr.h" #include "tcp_impl.h" #include "udp.h" #include "inet_chksum.h" #include "net_bridge.h" #include "lwip_customer.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define LWIP_NAT_TTL_INFINITE (-1) #define LWIP_NAT_TTL_SECONDS (60) #define LWIP_NAT_TTL_SECONDS_APP (60) #define LWIP_NAT_TTL_SECONDS_ICMP (60) #define LWIP_NAT_TTL_SECONDS_TCP (600) #define LWIP_NAT_TTL_SECONDS_TRIGGER (20) /** Timer interval at which to call ip_nat_tmr() */ #define LWIP_NAT_TMR_INTERVAL_SEC (10) /* network order, port 21 is for ftp */ #define NAT_TCP_PORT_20 (0x1400) /*21*/ #define NAT_TCP_PORT_21 (0x1500) /*21*/ #define NAT_TCP_PORT_PPTP (0xBB06) /*1723*/ #define NAT_TCP_PORT_DNS (0x3500) /*53*/ #define NAT_UDP_PORT_SIP (0xC413) /*5060*/ #define NAT_UDP_PORT_DNS (0x3500) /*53*/ #define NAT_UDP_PORT_DHCP_SERVER (0x4300) /*67*/ #define NAT_UDP_PORT_DHCP_CLIENT (0x4400) /*68*/ /* Return 1 if tcp port is a persist port */ #define _nat_tcp_port(port) ((port) == NAT_TCP_PORT_21 \ || (port) == NAT_TCP_PORT_PPTP) #define nat_tcp_persist_port(port) (_nat_tcp_port(port) || lwip_hook_nat_persistant_port(port)) /*****define for nat_entry->flags settings ******/ /** indicates this ipnat table if do tcp dns transfor */ #define NAT_FLAG_DNS_TRANSFER 0x0001 /** indicates this ipnat table if do ftp alg nat transfor */ #define NAT_FLAG_FTP_ALG_TRANSFER 0x0002 /** indicates this ipnat table need do tcp seq amend, for ftp alg */ #define NAT_FLAG_TCP_SEQ_AMEND 0x0004 /** indicates this ipnat table is ip nat entry for mifi */ #define NAT_FLAG_IP_NAT_ENTRY 0x0008 /** indicates this ipnat table is app nat entry */ #define NAT_FLAG_APP_NAT_ENTRY 0x0010 /** indicates this ipnat table created by dongle mode, for dongle fastpath */ #define NAT_FLAG_DONGLE_NAT_ENTRY 0x0020 /** indicates this ipnat table created by input trigger from nw for donglenat at */ #define NAT_FLAG_TRIGGER_NAT_ENTRY 0x0040 /** indicates this ipnat table created by fwd rule */ #define NAT_FLAG_FWD_NAT_ENTRY 0x0080 #define nat_is_dns_transfer(entry) (((entry)->flags & NAT_FLAG_DNS_TRANSFER) ? 1 : 0) #define nat_set_dns_transfer(entry) ((entry)->flags |= NAT_FLAG_DNS_TRANSFER) #define nat_is_ftpalg_transfer(entry) (((entry)->flags & NAT_FLAG_FTP_ALG_TRANSFER) ? 1 : 0) #define nat_set_ftpalg_transfer(entry) ((entry)->flags |= NAT_FLAG_FTP_ALG_TRANSFER) #define nat_is_tcpseq_amend(entry) (((entry)->flags & NAT_FLAG_TCP_SEQ_AMEND) ? 1 : 0) #define nat_set_tcpseq_amend(entry) ((entry)->flags |= NAT_FLAG_TCP_SEQ_AMEND) #define nat_is_ipnat_entry(entry) (((entry)->flags & NAT_FLAG_IP_NAT_ENTRY) ? 1 : 0) #define nat_set_ipnat_entry(entry) ((entry)->flags |= NAT_FLAG_IP_NAT_ENTRY) #define nat_is_appnat_entry(entry) (((entry)->flags & NAT_FLAG_APP_NAT_ENTRY) ? 1 : 0) #define nat_set_appnat_entry(entry) ((entry)->flags |= NAT_FLAG_APP_NAT_ENTRY) #define nat_is_donglenat_entry(entry) (((entry)->flags & NAT_FLAG_DONGLE_NAT_ENTRY) ? 1 : 0) #define nat_set_donglenat_entry(entry) ((entry)->flags |= NAT_FLAG_DONGLE_NAT_ENTRY) #define nat_is_trigger_entry(entry) (((entry)->flags & NAT_FLAG_TRIGGER_NAT_ENTRY) ? 1 : 0) #define nat_set_trigger_entry(entry) ((entry)->flags |= NAT_FLAG_TRIGGER_NAT_ENTRY) #define nat_is_fwd_entry(entry) (((entry)->flags & NAT_FLAG_FWD_NAT_ENTRY) ? 1 : 0) #define nat_set_fwd_entry(entry) ((entry)->flags |= NAT_FLAG_FWD_NAT_ENTRY) #define nat_is_infinite_entry(entry) (((entry)->ttl == LWIP_NAT_TTL_INFINITE) ? 1 : 0) #define nat_is_stable_flow_entry(entry) (((entry)->status == IP_NAT_STATUS_TCP_ESTABLISH) ? 1 : 0) #define nat_is_close_flow_entry(entry) (((entry)->status >= IP_NAT_STATUS_TCP_CLOSING) ? 1 : 0) #define ip_nat_chksum_adjust_len2(chksum, optr, nptr) inet_chksum_adjust_2n((chksum), (optr), (nptr), 1) #define ip_nat_chksum_adjust_len4(chksum, optr, nptr) inet_chksum_adjust_2n((chksum), (optr), (nptr), 2) typedef enum { IP_NAT_STATUS_INIT = 0, IP_NAT_STATUS_TCP_SYN, IP_NAT_STATUS_TCP_ESTABLISH, IP_NAT_STATUS_TCPSEQ_AMEND_START, IP_NAT_STATUS_TCPSEQ_AMEND_IN_STABLE, IP_NAT_STATUS_TCPSEQ_AMEND_OUT_STABLE, IP_NAT_STATUS_TCP_CLOSING, IP_NAT_STATUS_END } ip_nat_status; typedef enum { IP_NAT_UDP = 0x1UL, IP_NAT_TCP = 0x2UL, IP_NAT_ICMP = 0x3UL, IP_NAT_GRE = 0x4UL } ip_nat_type; typedef struct _ip_nat_icmp_t { u16_t id_new; u16_t id; u16_t seqno; u16_t seqno_new; } ip_nat_icmp_t; typedef struct _ip_nat_tcp_t { u16_t nport; u16_t sport; u16_t dport; s16_t seq_diff; /*tcp seqno diff value for one ftp alg process now*/ s32_t seq_amend; /*tcp seqno amend value for multi ftp alg one ftp connection*/ u32_t seq_next; /*tcp origin seq_next marker value for one ftp alg process*/ } ip_nat_tcp_t; typedef struct _ip_nat_udp_t { u16_t nport; u16_t sport; u16_t dport; } ip_nat_udp_t; typedef struct _ip_nat_table_t { s16_t ttl; // must be s16_t, -1 for not timer u16_t index; // record table index u32_t key; // hash table key, also keep same with UL flowid for mifi, and flowid for dongle ip_addr_t source; ip_addr_t dest; struct netif* netif_nw; //record internet netif, netif_cid** struct netif* netif_lc; //record local netif, netif_pc, netif_wifi #if LWIP_ARP net_mac_rec_t* netmac_rec; //record net_mac_rec for coming packet which is from #endif s8_t epsid; //record epsid to nat table, using for nat cache using u8_t proto; u8_t wdsc_dl; u8_t wdsc_ul; u16_t flags; //using flags to extend ip_nat_table u16_t status; //using to recorder tcp status u32_t ctick; //record create or update tick, for delete oldest check u32_t packets; //record how many packets match this nat_entry for stable flow u32_t flowid; //record flow id for DL direction, for nat_entry->key record UL direction for mifi union { ip_nat_icmp_t icmp; ip_nat_tcp_t tcp; ip_nat_udp_t udp; } u; } ip_nat_table_t; /* port fwd flag, bitmap settings */ #define PORT_FWD_INVALID (0x0) #define PORT_FWD_TCP (0x01) #define PORT_FWD_UDP (0x02) #define PORT_FWD_MAPPING (0x04) /*denote this table is used to do port mapping*/ /*port_fwd_item used to for port fwd function,*/ /*this struct used in functio process.*/ typedef struct _port_fwd_item // 12 bytes { /*flag of hotbit map, refer to port fwd flag, bitmap settings*/ u32_t flag; // 1 tcp, 2 udp, 3 both, 0 invalid /*local machine ipaddr*/ u32_t ipaddr; // network order /*when table used for port forward, port_start and port_end denote port range*/ /*when table used for port mapping, */ /* --port_start denote external port,*/ /* --port_end denote internal port,*/ u16_t port_start; // host order u16_t port_end; // host order ip_nat_table_t *nat_entry; /*record malloc nat_entry for fastpath*/ }port_fwd_item; /*port_fwd_list used to config port fwd function,*/ /*this struct opened for api call.*/ /*the meaning of data come from port_fwd_item*/ typedef struct _port_fwd_list { u32_t flag; // 1 tcp, 2 udp, 3 both, 0 invalid u32_t ipaddr; // network order u16_t port_start; // host order u16_t port_end; // host order struct _port_fwd_list *next; }port_fwd_list; static inline u32_t nat_make_tcp_hash_key(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr, int dlul) { if (LWIP_DL_DIRECTION == dlul) { return MAKE_HASH_KEY_NEW((iphdr->dest.addr) ^ (iphdr->src.addr), ntohs(tcphdr->dest) << 8UL, (((ntohs(tcphdr->src)) ^ (tcphdr->src)) & 0xF) << 4UL, IP_NAT_TCP); } else { return MAKE_HASH_KEY_NEW((iphdr->dest.addr) ^ (iphdr->src.addr), ntohs(tcphdr->src) << 8UL, (((ntohs(tcphdr->dest)) ^ (tcphdr->dest)) & 0xF) << 4UL, IP_NAT_TCP); } } static inline u32_t nat_make_udp_hash_key(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr, int dlul) { if (LWIP_DL_DIRECTION == dlul) { return MAKE_HASH_KEY_NEW((iphdr->dest.addr) ^ (iphdr->src.addr), ntohs(udphdr->dest) << 8UL, (((ntohs(udphdr->src)) ^ (udphdr->src)) & 0xF) << 4UL, IP_NAT_UDP); } else { return MAKE_HASH_KEY_NEW((iphdr->dest.addr) ^ (iphdr->src.addr), ntohs(udphdr->src) << 8UL, (((ntohs(udphdr->dest)) ^ (udphdr->dest)) & 0xF) << 4UL, IP_NAT_UDP); } } static inline u32_t nat_make_icmp_hash_key(const struct ip_hdr *iphdr, const struct icmp_echo_hdr *icmphdr, int dlul) { return MAKE_HASH_KEY_NEW(((iphdr->dest.addr) ^ (iphdr->src.addr)), (ntohs(icmphdr->seqno) & 0xFF) << 8UL, (ntohs(icmphdr->id) & 0xF) << 4UL, IP_NAT_ICMP); } static inline u32_t nat_make_gre_hash_key(const struct ip_hdr *iphdr, const void *grehdr, int dlul) { return MAKE_HASH_KEY_NEW(((iphdr->dest.addr) ^ (iphdr->src.addr)), (ntohs(IPH_PROTO(iphdr)) & 0xFF) << 8UL, (IPH_PROTO(iphdr) & 0xF) << 4UL, IP_NAT_GRE); } extern int lwip_nat_ttl_tcp_set; static inline void update_nat_entry_ttl(ip_nat_table_t * nat_entry, s32_t ttl) { if (LWIP_NAT_TTL_INFINITE == ttl) { nat_entry->ttl = LWIP_NAT_TTL_INFINITE; } else { nat_entry->ttl = (nat_entry->proto == IP_PROTO_TCP) ? lwip_nat_ttl_tcp_set : ttl; } nat_entry->ctick = OSAGetTicks(); } #if IP_NAT void ip_nat_init(void); void ip_nat_tmr(void); int ip_nat_input(struct netif *netif, struct pbuf **pbuf); int ip_nat_out(struct netif *netif, struct pbuf *p, int epsid); void *ip_nat_check_header(struct pbuf *p, u16_t min_size); ip_nat_table_t * ip_nat_tcp_output_hit_cache(struct pbuf *p); ip_nat_table_t * ip_nat_udp_output_hit_cache(struct pbuf *p); port_fwd_item *ip_fwd_output(struct pbuf* p); void ip_nat_tcp_mangle_window(struct netif *netif_in, ip_nat_table_t * nat_entry, struct tcp_hdr *tcphdr); void ip_nat_mangle_ftp(struct netif *netif, struct pbuf ** ppbuf); int app_hash_cache_get_in_tcp(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr, int nat_flag); int app_hash_cache_get_out_tcp(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr, int nat_flag); int app_hash_cache_get_in_udp(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr, int nat_flag); int app_hash_cache_get_out_udp(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr, int nat_flag); ip_nat_table_t * app_nat_key_hit_cache(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr, const struct udp_hdr *udphdr, u32_t flowid, int nat_flag); #endif /* IP_NAT */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __LWIP_NAT_H__ */