| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400 |
- /*
- NAPT(Network Address Port Translation)
- IPv4版本的NAPT,支持TCP/UDP/ICMP协议
- 原版代码来源:
- https://gitee.com/openLuat/luatos-soc-air101
- https://www.winnermicro.com/html/1/156/158/558.html
- 为适应luatos环境做了大量修改, 脱离了平台依赖性
- */
- #include "luat_base.h"
- #include <stdio.h>
- #include <string.h>
- #include "lwip/ip.h"
- #include "lwip/udp.h"
- #include "lwip/icmp.h"
- #include "lwip/dns.h"
- #include "lwip/priv/tcp_priv.h"
- #include "lwip/timeouts.h"
- #include "luat_napt.h"
- #include "luat_mem.h"
- #define LUAT_LOG_TAG "napt"
- #include "luat_log.h"
- //#define NAPT_ALLOC_DEBUG
- #ifdef NAPT_ALLOC_DEBUG
- static u16 napt4ic_cnt;
- static u16 napt4tcp_cnt;
- static u16 napt4udp_cnt;
- #endif
- //#define NAPT_DEBUG
- #ifdef NAPT_DEBUG
- #define NAPT_PRINT printf
- #else
- #define NAPT_PRINT(...)
- #endif
- #define IP_PROTO_GRE 47
- #define NAPT_ETH_HDR_LEN sizeof(struct ethhdr)
- #define NAPT_CHKSUM_16BIT_LEN sizeof(u16)
- #define NAPT_TABLE_FOREACH(pos, head)\
- for (pos = head.next; NULL != pos; pos = pos->next)
- /* napt tcp/udp */
- struct napt_addr_4tu{
- struct napt_addr_4tu *next;
- u16 src_port;
- u16 new_port;
- u8 src_ip;
- u8 time_stamp;
- u8 mac[6];
- };
- /* napt icmp */
- struct napt_addr_4ic{
- struct napt_addr_4ic *next;
- u16 src_id;/* icmp id */
- u16 new_id;
- u8 src_ip;
- u8 time_stamp;
- u8 mac[6];
- };
- struct napt_addr_gre{
- u8 src_ip;
- u8 time_stamp;
- u8 is_used;
- u8 mac[6];
- };
- struct napt_table_head_4tu{
- struct napt_addr_4tu *next;
- #ifdef NAPT_TABLE_LIMIT
- u16 cnt;
- #endif
- };
- struct napt_table_head_4ic{
- struct napt_addr_4ic *next;
- #ifdef NAPT_TABLE_LIMIT
- u16 cnt;
- #endif
- };
- /* napt head */
- static struct napt_table_head_4tu napt_table_4tcp;
- static struct napt_table_head_4tu napt_table_4udp;
- static struct napt_table_head_4ic napt_table_4ic;
- //#define NAPT_USE_HW_TIMER
- //#define NAPT_TABLE_MUTEX_LOCK
- #ifdef NAPT_TABLE_MUTEX_LOCK
- static tls_os_sem_t *napt_table_lock_4tcp;
- static tls_os_sem_t *napt_table_lock_4udp;
- static tls_os_sem_t *napt_table_lock_4ic;
- #ifdef NAPT_USE_HW_TIMER
- static bool napt_check_tcp = FALSE;
- static bool napt_check_udp = FALSE;
- static bool napt_check_ic = FALSE;
- #endif /* NAPT_USE_HW_TIMER */
- #endif /* NAPT_TABLE_MUTEX_LOCK */
- /* tcp&udp */
- static u16 napt_curr_port;
- /* icmp id */
- static u16 napt_curr_id;
- /* gre for vpn */
- static struct napt_addr_gre gre_info;
- static inline void *luat_napt_mem_alloc(u32 size)
- {
- return luat_heap_malloc(size);
- }
- static inline void luat_napt_mem_free(void *p)
- {
- luat_heap_free(p);
- }
- /*****************************************************************************
- Prototype : luat_napt_try_lock
- Description : try hold lock
- Input : tls_os_sem_t *lock point lock
- Output : None
- Return Value : int 0 success
- -1 failed
- ------------------------------------------------------------------------------
-
- History :
- 1.Date : 2019/2/1
- Author : Li Limin, lilm@winnermicro.com
- Modification : Created function
- *****************************************************************************/
- // static inline int luat_napt_try_lock(tls_os_sem_t *lock)
- // {
- // return (tls_os_sem_acquire(lock, HZ / 10) == TLS_OS_SUCCESS) ? 0 : -1;
- // return 0;
- // }
- /*****************************************************************************
- Prototype : luat_napt_lock
- Description : hold lock
- Input : tls_os_sem_t *lock point lock
- Output : None
- Return Value : void
- ------------------------------------------------------------------------------
-
- History :
- 1.Date : 2019/2/1
- Author : Li Limin, lilm@winnermicro.com
- Modification : Created function
- *****************************************************************************/
- // static inline void luat_napt_lock(tls_os_sem_t *lock)
- // {
- // tls_os_sem_acquire(lock, 0);
- // return;
- // }
- /*****************************************************************************
- Prototype : luat_napt_unlock
- Description : release lock
- Input : tls_os_sem_t *lock point lock
- Output : None
- Return Value : void
- ------------------------------------------------------------------------------
-
- History :
- 1.Date : 2019/2/1
- Author : Li Limin, lilm@winnermicro.com
- Modification : Created function
- *****************************************************************************/
- // static inline void luat_napt_unlock(tls_os_sem_t *lock)
- // {
- // tls_os_sem_release(lock);
- // }
- #ifdef NAPT_TABLE_LIMIT
- /*****************************************************************************
- Prototype : luat_napt_table_is_full
- Description : the napt table is full
- Input : void
- Output : None
- Return Value : bool true the napt table is full
- false the napt table not is full
- ------------------------------------------------------------------------------
-
- History :
- 1.Date : 2015/3/10
- Author : Li Limin, lilm@winnermicro.com
- Modification : Created function
- *****************************************************************************/
- static inline bool luat_napt_table_is_full(void)
- {
- bool is_full = false;
- if ((napt_table_4tcp.cnt + napt_table_4udp.cnt + napt_table_4ic.cnt) >= NAPT_TABLE_SIZE_MAX)
- {
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@@ napt batle: limit is reached for tcp/udp.\r\n");
- #endif
- NAPT_PRINT("napt batle: limit is reached for tcp/udp.\n");
- is_full = true;
- }
- return is_full;
- }
- #endif
- static inline u16 luat_napt_port_alloc(void)
- {
- u8_t i;
- u16 cnt = 0;
- struct udp_pcb *udp_pcb;
- struct tcp_pcb *tcp_pcb;
- struct napt_addr_4tu *napt_tcp;
- struct napt_addr_4tu *napt_udp;
- again:
- if (napt_curr_port++ == NAPT_LOCAL_PORT_RANGE_END)
- {
- napt_curr_port = NAPT_LOCAL_PORT_RANGE_START;
- }
- /* udp */
- for(udp_pcb = udp_pcbs; udp_pcb != NULL; udp_pcb = udp_pcb->next)
- {
- if (udp_pcb->local_port == napt_curr_port)
- {
- if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START))
- {
- return 0;
- }
- goto again;
- }
- }
- /* tcp */
- for (i = 0; i < NUM_TCP_PCB_LISTS; i++)
- {
- for(tcp_pcb = *tcp_pcb_lists[i]; tcp_pcb != NULL; tcp_pcb = tcp_pcb->next)
- {
- if (tcp_pcb->local_port == napt_curr_port)
- {
- if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START))
- {
- return 0;
- }
- goto again;
- }
- }
- }
- /* tcp napt */
- NAPT_TABLE_FOREACH(napt_tcp, napt_table_4tcp)
- {
- if (napt_tcp->new_port == napt_curr_port)
- {
- if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START))
- {
- return 0;
- }
- goto again;
- }
- }
- /* udp napt */
- NAPT_TABLE_FOREACH(napt_udp, napt_table_4udp)
- {
- if (napt_udp->new_port == napt_curr_port)
- {
- if (++cnt > (NAPT_LOCAL_PORT_RANGE_END - NAPT_LOCAL_PORT_RANGE_START))
- {
- return 0;
- }
- goto again;
- }
- }
- return napt_curr_port;
- }
- static inline struct napt_addr_4ic *luat_napt_get_by_src_id(u16 id, u8 ip)
- {
- struct napt_addr_4ic *ret = NULL;
- struct napt_addr_4ic *napt;
- NAPT_TABLE_FOREACH(napt, napt_table_4ic)
- {
- if ((id == napt->src_id) && (ip == napt->src_ip))
- {
- ret = napt;
- break;
- }
- }
- return ret;
- }
- static inline struct napt_addr_4ic *luat_napt_get_by_dst_id(u16 id)
- {
- struct napt_addr_4ic *ret = NULL;
- struct napt_addr_4ic *napt;
- NAPT_TABLE_FOREACH(napt, napt_table_4ic)
- {
- if (id == napt->new_id)
- {
- ret = napt;
- break;
- }
- }
- return ret;
- }
- static u16 luat_napt_icmp_id_alloc(void)
- {
- u16 cnt = 0;
- struct napt_addr_4ic *napt;
- again:
- if (napt_curr_id++ == NAPT_ICMP_ID_RANGE_END)
- {
- napt_curr_id = NAPT_ICMP_ID_RANGE_START;
- }
- NAPT_TABLE_FOREACH(napt, napt_table_4ic)
- {
- if (napt_curr_id == napt->new_id)
- {
- if (++cnt > (NAPT_ICMP_ID_RANGE_END - NAPT_ICMP_ID_RANGE_START))
- {
- return 0;
- }
- goto again;
- }
- }
- return napt_curr_id;
- }
- static inline struct napt_addr_4ic *luat_napt_table_insert_4ic(u16 id, u8 ip)
- {
- struct napt_addr_4ic *napt;
- #ifdef NAPT_TABLE_LIMIT
- if (true == luat_napt_table_is_full())
- {
- return NULL;
- }
- #endif
- napt = luat_napt_mem_alloc(sizeof(struct napt_addr_4ic));
- if (NULL == napt)
- {
- return NULL;
- }
- memset(napt, 0, sizeof(struct napt_addr_4ic));
- napt->src_id = id;
- napt->new_id = luat_napt_icmp_id_alloc();
- if (0 == napt->new_id)
- {
- luat_napt_mem_free(napt);
- return NULL;
- }
- napt->src_ip = ip;
- napt->time_stamp++;
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4ic.cnt++;
- #endif
- napt->next = napt_table_4ic.next;
- napt_table_4ic.next = napt;
-
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt id alloc %hu\r\n", ++napt4ic_cnt);
- #endif
- return napt;
- }
- static inline void luat_napt_table_update_4ic(struct napt_addr_4ic *napt)
- {
- if (!++napt->time_stamp)
- napt->time_stamp++;
- return;
- }
- static inline struct napt_addr_4tu *luat_napt_get_tcp_port_by_dest(u16 port)
- {
- struct napt_addr_4tu *ret = NULL;
- struct napt_addr_4tu *napt;
- NAPT_TABLE_FOREACH(napt, napt_table_4tcp)
- {
- if (napt->new_port == port)
- {
- ret = napt;
- break;
- }
- }
- return ret;
- }
- static inline struct napt_addr_4tu *luat_napt_get_tcp_port_by_src(u16 port, u8 ip)
- {
- struct napt_addr_4tu *ret = NULL;
- struct napt_addr_4tu *napt;
- NAPT_TABLE_FOREACH(napt, napt_table_4tcp)
- {
- if (port == napt->src_port)
- {
- if (ip == napt->src_ip)
- {
- ret = napt;
- break;
- }
- }
- }
- return ret;
- }
- static inline struct napt_addr_4tu *luat_napt_table_insert_4tcp(u16 src_port, u8 ip)
- {
- u16 new_port;
- struct napt_addr_4tu *napt;
- #ifdef NAPT_TABLE_LIMIT
- if (true == luat_napt_table_is_full())
- {
- return NULL;
- }
- #endif
- napt = luat_napt_mem_alloc(sizeof(struct napt_addr_4tu));
- if (NULL == napt)
- {
- return NULL;
- }
- memset(napt, 0, sizeof(struct napt_addr_4tu));
- napt->src_port = src_port;
- new_port = luat_napt_port_alloc();
- if (0 == new_port)
- {
- luat_napt_mem_free(napt);
- return NULL;
- }
- napt->new_port = htons(new_port);
- napt->src_ip = ip;
- napt->time_stamp++;
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4tcp.cnt++;
- #endif
- napt->next = napt_table_4tcp.next;
- napt_table_4tcp.next = napt;
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt tcp port alloc %hu\r\n", ++napt4tcp_cnt);
- #endif
- return napt;
- }
- static inline void luat_napt_table_update_4tcp(struct napt_addr_4tu *napt)
- {
- if (!++napt->time_stamp)
- napt->time_stamp++;
- return;
- }
- static inline struct napt_addr_4tu *luat_napt_get_udp_port_by_dest(u16 port)
- {
- struct napt_addr_4tu *ret = NULL;
- struct napt_addr_4tu *napt;
- NAPT_TABLE_FOREACH(napt, napt_table_4udp)
- {
- if (napt->new_port == port)
- {
- ret = napt;
- break;
- }
- }
- return ret;
- }
- static inline struct napt_addr_4tu *luat_napt_get_udp_port_by_src(u16 port, u8 ip)
- {
- struct napt_addr_4tu *ret = NULL;
- struct napt_addr_4tu *napt;
- NAPT_TABLE_FOREACH(napt, napt_table_4udp)
- {
- if (port == napt->src_port)
- {
- if (ip == napt->src_ip)
- {
- ret = napt;
- break;
- }
- }
- }
- return ret;
- }
- static inline struct napt_addr_4tu *luat_napt_table_insert_4udp(u16 src_port, u8 ip)
- {
- u16 new_port;
- struct napt_addr_4tu *napt;
- #ifdef NAPT_TABLE_LIMIT
- if (true == luat_napt_table_is_full())
- {
- return NULL;
- }
- #endif
- napt = luat_napt_mem_alloc(sizeof(struct napt_addr_4tu));
- if (NULL == napt)
- {
- return NULL;
- }
- memset(napt, 0, sizeof(struct napt_addr_4tu));
- napt->src_port = src_port;
- new_port = luat_napt_port_alloc();
- if (0 == new_port)
- {
- luat_napt_mem_free(napt);
- return NULL;
- }
- napt->new_port = htons(new_port);
- napt->src_ip = ip;
- napt->time_stamp++;
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4udp.cnt++;
- #endif
- napt->next = napt_table_4udp.next;
- napt_table_4udp.next = napt;
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt udp port alloc %hu\r\n", ++napt4udp_cnt);
- #endif
- return napt;
- }
- static inline void luat_napt_table_update_4udp(struct napt_addr_4tu *napt)
- {
- if (!++napt->time_stamp)
- napt->time_stamp++;
- return;
- }
- static void luat_napt_table_check_4tcp(void)
- {
- struct napt_addr_4tu *napt4tcp;
- struct napt_addr_4tu *napt4tcp_prev;
- /* tcp */
- #ifdef NAPT_TABLE_MUTEX_LOCK
- #ifdef NAPT_USE_HW_TIMER
- if (luat_napt_try_lock(napt_table_lock_4tcp))
- {
- //printf("## try tcp\r\n");
- napt_check_tcp = TRUE;
- return;
- }
- napt_check_tcp = FALSE;
- #else
- luat_napt_lock(napt_table_lock_4tcp);
- #endif
- #endif
- for (napt4tcp_prev = napt_table_4tcp.next;\
- NULL != napt4tcp_prev;\
- napt4tcp_prev = napt4tcp_prev->next)
- {
- napt4tcp = napt4tcp_prev->next;
- if (NULL != napt4tcp)
- {
- if (0 == napt4tcp->time_stamp)
- {
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4tcp.cnt--;
- #endif
- napt4tcp_prev->next = napt4tcp->next;
- napt4tcp->next = NULL;
- luat_napt_mem_free(napt4tcp);
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt tcp port free %hu\r\n", --napt4tcp_cnt);
- #endif
- }
- else
- {
- napt4tcp->time_stamp = 0;
- }
- }
-
- }
- napt4tcp = napt_table_4tcp.next;
- if (NULL != napt4tcp)
- {
- if (0 == napt4tcp->time_stamp)
- {
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4tcp.cnt--;
- #endif
- napt_table_4tcp.next = napt4tcp->next;
- napt4tcp->next = NULL;
- luat_napt_mem_free(napt4tcp);
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt tcp port free %hu\r\n", --napt4tcp_cnt);
- #endif
- }
- else
- {
- napt4tcp->time_stamp = 0;
- }
- }
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4tcp);
- #endif
- return;
- }
- static void luat_napt_table_check_4udp(void)
- {
- struct napt_addr_4tu *napt4udp;
- struct napt_addr_4tu *napt4udp_prev;
- /* udp */
- #ifdef NAPT_TABLE_MUTEX_LOCK
- #ifdef NAPT_USE_HW_TIMER
- if (luat_napt_try_lock(napt_table_lock_4udp))
- {
- //printf("## try udp\r\n");
- napt_check_udp = TRUE;
- return;
- }
- napt_check_udp = FALSE;
- #else
- luat_napt_lock(napt_table_lock_4udp);
- #endif
- #endif
- for (napt4udp_prev = napt_table_4udp.next;\
- NULL != napt4udp_prev;\
- napt4udp_prev = napt4udp_prev->next)
- {
- napt4udp = napt4udp_prev->next;
- if (NULL != napt4udp)
- {
- if (0 == napt4udp->time_stamp)
- {
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4udp.cnt--;
- #endif
- napt4udp_prev->next = napt4udp->next;
- napt4udp->next = NULL;
- luat_napt_mem_free(napt4udp);
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt udp port free %hu\r\n", --napt4udp_cnt);
- #endif
- }
- else
- {
- napt4udp->time_stamp = 0;
- }
- }
-
- }
- napt4udp = napt_table_4udp.next;
- if (NULL != napt4udp)
- {
- if (0 == napt4udp->time_stamp)
- {
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4udp.cnt--;
- #endif
- napt_table_4udp.next = napt4udp->next;
- napt4udp->next = NULL;
- luat_napt_mem_free(napt4udp);
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt udp port free %hu\r\n", --napt4udp_cnt);
- #endif
- }
- else
- {
- napt4udp->time_stamp = 0;
- }
- }
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4udp);
- #endif
- return;
- }
- static void luat_napt_table_check_4ic(void)
- {
- struct napt_addr_4ic *napt4ic;
- struct napt_addr_4ic *napt4ic_prev;
- /* icmp */
- #ifdef NAPT_TABLE_MUTEX_LOCK
- #ifdef NAPT_USE_HW_TIMER
- if (luat_napt_try_lock(napt_table_lock_4ic))
- {
- //printf("## try ic\r\n");
- napt_check_ic = TRUE;
- return;
- }
- napt_check_ic = FALSE;
- #else
- luat_napt_lock(napt_table_lock_4ic);
- #endif
- #endif
- /* skip the first item */
- for (napt4ic_prev = napt_table_4ic.next;\
- NULL != napt4ic_prev;\
- napt4ic_prev = napt4ic_prev->next)
- {
- napt4ic = napt4ic_prev->next;
- if (NULL != napt4ic)
- {
- if (0 == napt4ic->time_stamp)
- {
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4ic.cnt--;
- #endif
- napt4ic_prev->next = napt4ic->next;
- napt4ic->next = NULL;
- luat_napt_mem_free(napt4ic);
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt id free %hu\r\n", --napt4ic_cnt);
- #endif
- }
- else
- {
- napt4ic->time_stamp = 0;
- }
- }
-
- }
- /* check the first item */
- napt4ic = napt_table_4ic.next;
- if (NULL != napt4ic)
- {
- if (0 == napt4ic->time_stamp)
- {
- #ifdef NAPT_TABLE_LIMIT
- napt_table_4ic.cnt--;
- #endif
- napt_table_4ic.next = napt4ic->next;
- napt4ic->next = NULL;
- luat_napt_mem_free(napt4ic);
- #ifdef NAPT_ALLOC_DEBUG
- printf("@@ napt id free %hu\r\n", --napt4ic_cnt);
- #endif
- }
- else
- {
- napt4ic->time_stamp = 0;
- }
- }
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4ic);
- #endif
- return;
- }
- static void luat_napt_table_check_4gre(void)
- {
- if (0 == gre_info.time_stamp)
- {
- gre_info.is_used = 0;
- //gre_info.src_ip = 0;
- }
- else
- {
- gre_info.time_stamp = 0;
- }
- return;
- }
- void luat_napt_table_check(void *arg)
- {
- luat_napt_table_check_4tcp();
- luat_napt_table_check_4udp();
- luat_napt_table_check_4ic();
- luat_napt_table_check_4gre();
- return;
- }
- #ifdef NAPT_USE_HW_TIMER
- static void luat_napt_table_check_try(void)
- {
- if (napt_check_tcp)
- luat_napt_table_check_4tcp();
- if (napt_check_udp)
- luat_napt_table_check_4udp();
- if (napt_check_ic)
- luat_napt_table_check_4ic();
- return;
- }
- #endif
- static inline u32 alg_hdr_16bitsum(const u16 *buff, u16 len)
- {
- u32 sum = 0;
- u16 *pos = (u16 *)buff;
- u16 remainder_size = len;
- while (remainder_size > 1)
- {
- sum += *pos ++;
- remainder_size -= NAPT_CHKSUM_16BIT_LEN;
- }
- if (remainder_size > 0)
- {
- sum += *(u8*)pos;
- }
- return sum;
- }
- static inline u16 alg_iphdr_chksum(const u16 *buff, u16 len)
- {
- u32 sum = alg_hdr_16bitsum(buff, len);
- sum = (sum >> 16) + (sum & 0xFFFF);
- sum += (sum >> 16);
- return (u16)(~sum);
- }
- static inline u16 alg_tcpudphdr_chksum(u32 src_addr, u32 dst_addr, u8 proto,
- const u16 *buff, u16 len)
- {
- u32 sum = 0;
- sum += (src_addr & 0xffffUL);
- sum += ((src_addr >> 16) & 0xffffUL);
- sum += (dst_addr & 0xffffUL);
- sum += ((dst_addr >> 16) & 0xffffUL);
- sum += (u32)htons((u16)proto);
- sum += (u32)htons(len);
- sum += alg_hdr_16bitsum(buff, len);
- sum = (sum >> 16) + (sum & 0xFFFF);
- sum += (sum >> 16);
- return (u16)(~sum);
- }
- static int alg_icmp_proc(u8 is_inet,
- struct ip_hdr *ip_hdr,
- ip_addr_t* gw_ip)
- {
- struct napt_addr_4ic *napt;
- struct icmp_echo_hdr *icmp_hdr;
- u8* ptr = ((u8*)ip_hdr) - 14;
- u8 iphdr_len;
- iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4;
- icmp_hdr = (struct icmp_echo_hdr *)((u8 *)ip_hdr + iphdr_len);
- if (is_inet)
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4ic);
- #endif
- napt = luat_napt_get_by_src_id(icmp_hdr->id, ip_hdr->src.addr >> 24);
- if (NULL == napt)
- {
- napt = luat_napt_table_insert_4ic(icmp_hdr->id, ip_hdr->src.addr >> 24);
- if (NULL == napt)
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4ic);
- #endif
- return -1;
- }
- }
- else
- {
- luat_napt_table_update_4ic(napt);
- }
- icmp_hdr->id = napt->new_id;
- memcpy(napt->mac, ptr + 6, 6);
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4ic);
- #endif
- icmp_hdr->chksum = 0;
- icmp_hdr->chksum = alg_iphdr_chksum((u16 *)icmp_hdr, ntohs(ip_hdr->_len) - iphdr_len);
- ip_hdr->src.addr = ip_addr_get_ip4_u32(gw_ip);
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- return 0; // 已经改造完成, 可以返回了
- }
- else
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4ic);
- #endif
- napt = luat_napt_get_by_dst_id(icmp_hdr->id);
- if (NULL != napt)
- {
- //luat_napt_table_update_4ic(napt);
- icmp_hdr->id = napt->src_id;
- icmp_hdr->chksum = 0;
- icmp_hdr->chksum = alg_iphdr_chksum((u16 *)icmp_hdr, ntohs(ip_hdr->_len) - iphdr_len);
- ip_hdr->dest.addr = ((napt->src_ip) << 24) | (ip_addr_get_ip4_u32(gw_ip) & 0x00ffffff);
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4ic);
- #endif
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- memcpy(ptr, napt->mac, 6);
- return 0; // 已经改造完成, 可以返回了
- }
- else
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4ic);
- #endif
- }
- }
- return -1;
- }
- static int alg_tcp_proc(u8 is_inet,
- struct ip_hdr *ip_hdr,
- ip_addr_t* gw_ip)
- {
- u8 src_ip;
- struct napt_addr_4tu *napt;
- struct tcp_hdr *tcp_hdr;
- u8* ptr = ((u8*)ip_hdr) - 14;
- u8 iphdr_len;
- iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4;
- tcp_hdr = (struct tcp_hdr *)((u8 *)ip_hdr + iphdr_len);
- if (is_inet)
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4tcp);
- #endif
- src_ip = ip_hdr->src.addr >> 24;
- napt = luat_napt_get_tcp_port_by_src(tcp_hdr->src, src_ip);
- if (NULL == napt)
- {
- napt = luat_napt_table_insert_4tcp(tcp_hdr->src, src_ip);
- if (NULL == napt)
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4tcp);
- #endif
- return -1;
- }
- // LLOGD("分配新的TCP映射 ip %d port %d -> %d", src_ip, tcp_hdr->src, napt->new_port);
- }
- else
- {
- luat_napt_table_update_4tcp(napt);
- // LLOGD("复用老的TCP映射 ip %d port %d -> %d", src_ip, tcp_hdr->src, napt->new_port);
- }
- memcpy(napt->mac, ptr + 6, 6); //保存源mac地址
- // LLOGD("记录内网-->外网的源MAC %02X%02X%02X%02X%02X%02X", napt->mac[0], napt->mac[1], napt->mac[2], napt->mac[3], napt->mac[4], napt->mac[5]);
- tcp_hdr->src = napt->new_port;
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4tcp);
- #endif
- ip_hdr->src.addr = ip_addr_get_ip4_u32(gw_ip);
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- tcp_hdr->chksum = 0;
- tcp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr,
- ip_hdr->dest.addr,
- IP_PROTO_TCP,
- (u16 *)tcp_hdr,
- ntohs(ip_hdr->_len) - iphdr_len);
- return 0;
- }
- /* from ap... */
- else
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4tcp);
- #endif
- napt = luat_napt_get_tcp_port_by_dest(tcp_hdr->dest);
- /* forward to sta... */
- if (NULL != napt)
- {
- //luat_napt_table_update_4tcp(napt);
- ip_hdr->dest.addr = (napt->src_ip << 24) | (ip_addr_get_ip4_u32(gw_ip) & 0x00ffffff);
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- tcp_hdr->dest = napt->src_port;
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4tcp);
- #endif
- tcp_hdr->chksum = 0;
- tcp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr,
- ip_hdr->dest.addr,
- IP_PROTO_TCP,
- (u16 *)tcp_hdr,
- ntohs(ip_hdr->_len) - iphdr_len);
- memcpy(ptr, napt->mac, 6); // 还原MAC地址
- return 0;
- }
- /* deliver to default gateway */
- else
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4tcp);
- #endif
- }
- }
- return -1;
- }
- static int alg_udp_proc(u8 is_inet,
- struct ip_hdr *ip_hdr,
- ip_addr_t* gw_ip)
- {
- u8 src_ip;
- struct napt_addr_4tu *napt;
- struct udp_hdr *udp_hdr;
- u8* ptr = ((u8*)ip_hdr) - 14;
- u8 iphdr_len;
- iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4;
- udp_hdr = (struct udp_hdr *)((u8 *)ip_hdr + iphdr_len);
- /* from sta... */
- if (is_inet)
- {
- /* create/update napt item */
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4udp);
- #endif
- src_ip = ip_hdr->src.addr >> 24;
- napt = luat_napt_get_udp_port_by_src(udp_hdr->src, src_ip);
- if (NULL == napt)
- {
- napt = luat_napt_table_insert_4udp(udp_hdr->src, src_ip);
- if (NULL == napt)
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4udp);
- #endif
- return -1;
- }
- }
- else
- {
- luat_napt_table_update_4udp(napt);
- }
- udp_hdr->src = napt->new_port;
- memcpy(napt->mac, ptr + 6, 6); // 拷贝源MAC地址
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4udp);
- #endif
- // redo:
- ip_hdr->src.addr = ip_addr_get_ip4_u32(gw_ip);
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- if (0 != udp_hdr->chksum)
- {
- udp_hdr->chksum = 0;
- udp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr,
- ip_hdr->dest.addr,
- IP_PROTO_UDP,
- (u16 *)udp_hdr,
- ntohs(ip_hdr->_len) - iphdr_len);
- }
- return 0;
- }
- /* form ap... */
- else
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4udp);
- #endif
- napt = luat_napt_get_udp_port_by_dest(udp_hdr->dest);
- /* forward to sta... */
- if (NULL != napt)
- {
- luat_napt_table_update_4udp(napt);
- ip_hdr->dest.addr = (napt->src_ip << 24) | (ip_addr_get_ip4_u32(gw_ip) & 0x00ffffff);
- udp_hdr->dest = napt->src_port;
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4udp);
- #endif
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- if (0 != udp_hdr->chksum)
- {
- udp_hdr->chksum = 0;
- udp_hdr->chksum = alg_tcpudphdr_chksum(ip_hdr->src.addr,
- ip_hdr->dest.addr,
- IP_PROTO_UDP,
- (u16 *)udp_hdr,
- ntohs(ip_hdr->_len) - iphdr_len);
- }
- memcpy(ptr, napt->mac, 6);
- return 0;
- }
- /* deliver to default gateway */
- else
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4udp);
- #endif
- }
- }
- // end:
- return -1;
- }
- static int alg_gre_proc(u8 is_inet, struct ip_hdr *ip_hdr, ip_addr_t* gw_ip)
- {
- // int err;
- u8 src_ip;
- u8 iphdr_len;
- iphdr_len = (ip_hdr->_v_hl & 0x0F) * 4;
- /* from sta... */
- if (is_inet)
- {
- src_ip = ip_hdr->src.addr >> 24;
- if (src_ip == gre_info.src_ip) /* current vpn */
- {
- gre_info.time_stamp++;
- }
- else if (1 == gre_info.is_used)/* vpn used */
- {
- return -1;
- }
- else /* new vpn */
- {
- gre_info.is_used = 1;
- gre_info.src_ip = src_ip;
- if (!++gre_info.time_stamp)
- gre_info.time_stamp++;
- }
- ip_hdr->src.addr = ip_addr_get_ip4_u32(gw_ip);
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- return 0;
- }
- /* from ap... */
- else
- {
- ip_hdr->dest.addr = (gre_info.src_ip << 24) | (ip_addr_get_ip4_u32(gw_ip) & 0x00ffffff);
- ip_hdr->_chksum = 0;
- ip_hdr->_chksum = alg_iphdr_chksum((u16 *)ip_hdr, iphdr_len);
- return 0;
- }
- }
- int luat_napt_input(u8 is_inet, u8 *pkt_body, u32 pkt_len, ip_addr_t* gw_ip)
- {
- int err = -1;
- struct ip_hdr *ip_hdr = NULL;
- #ifdef NAPT_USE_HW_TIMER
- luat_napt_table_check_try();
- #endif
- ip_hdr = (struct ip_hdr *)(pkt_body + 14);
- switch(ip_hdr->_proto)
- {
- case IP_PROTO_ICMP:
- {
- err = alg_icmp_proc(is_inet, ip_hdr, gw_ip);
- if (err)
- LLOGD("ICMP包 rc %d", err);
- break;
- }
- case IP_PROTO_TCP:
- {
- err = alg_tcp_proc(is_inet, ip_hdr, gw_ip);
- if (err)
- LLOGD("TCP包 rc %d", err);
- break;
- }
- case IP_PROTO_UDP:
- {
- err = alg_udp_proc(is_inet, ip_hdr, gw_ip);
- if (err)
- LLOGD("UDP包 rc %d", err);
- break;
- }
- case IP_PROTO_GRE:/* vpn */
- {
- err = alg_gre_proc(is_inet, ip_hdr, gw_ip);
- if (err)
- LLOGD("GRE包 rc %d", err);
- break;
- }
- default:
- {
- LLOGW("不认识的协议包 0x%02X", ip_hdr->_proto);
- err = -1;
- break;
- }
- }
- return err;
- }
- u8 luat_napt_port_is_used(u16 port)
- {
- u8 is_used = 0;
- struct napt_addr_4tu *napt_tcp;
- struct napt_addr_4tu *napt_udp;
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4tcp);
- #endif
- NAPT_TABLE_FOREACH(napt_tcp, napt_table_4tcp)
- {
- if (port == napt_tcp->new_port)
- {
- is_used = 1;
- break;
- }
- }
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4tcp);
- #endif
- if (1 != is_used)
- {
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_lock(napt_table_lock_4udp);
- #endif
- NAPT_TABLE_FOREACH(napt_udp, napt_table_4udp)
- {
- if (port == napt_udp->new_port)
- {
- is_used = 1;
- break;
- }
- }
- #ifdef NAPT_TABLE_MUTEX_LOCK
- luat_napt_unlock(napt_table_lock_4udp);
- #endif
- }
- return is_used;
- }
- int luat_napt_init(void)
- {
- int err = 0;
- #ifdef NAPT_USE_HW_TIMER
- struct tls_timer_cfg timer_cfg;
- #endif
- memset(&napt_table_4tcp, 0, sizeof(struct napt_table_head_4tu));
- memset(&napt_table_4udp, 0, sizeof(struct napt_table_head_4tu));
- memset(&napt_table_4ic, 0, sizeof(struct napt_table_head_4ic));
- napt_curr_port = NAPT_LOCAL_PORT_RANGE_START;
- napt_curr_id = NAPT_ICMP_ID_RANGE_START;
- #ifdef NAPT_TABLE_MUTEX_LOCK
- err = tls_os_sem_create(&napt_table_lock_4tcp, 1);
- if (TLS_OS_SUCCESS != err)
- {
- NAPT_PRINT("failed to init alg.\n");
- return err;
- }
- err = tls_os_sem_create(&napt_table_lock_4udp, 1);
- if (TLS_OS_SUCCESS != err)
- {
- NAPT_PRINT("failed to init alg.\n");
- return err;
- }
- err = tls_os_sem_create(&napt_table_lock_4ic, 1);
- if (TLS_OS_SUCCESS != err)
- {
- NAPT_PRINT("failed to init alg.\n");
- }
- #endif
- #ifdef NAPT_ALLOC_DEBUG
- napt4ic_cnt = 0;
- napt4tcp_cnt = 0;
- napt4udp_cnt = 0;
- #endif
- #ifdef NAPT_USE_HW_TIMER
- memset(&timer_cfg, 0, sizeof(timer_cfg));
- timer_cfg.unit = TLS_TIMER_UNIT_MS;
- timer_cfg.timeout = NAPT_TMR_INTERVAL;
- timer_cfg.is_repeat = TRUE;
- timer_cfg.callback = luat_napt_table_check;
- err = tls_timer_create(&timer_cfg);
- if (WM_TIMER_ID_INVALID != err)
- {
- tls_timer_start(err);
- err = 0;
- }
- else
- {
- NAPT_PRINT("failed to init alg timer.\n");
- }
- #else
- #endif
- return err;
- }
|