void NAT_ALG_TCP_checksum ( IP_HEADER_PTR ip_header_ptr /* [IN] pointer to IP header */ ) { /* Body */ TRANSPORT_UNION transport; uint16_t checksum; uint16_t protocol; uint16_t iplen = IPH_LEN(ip_header_ptr); uint16_t len = mqx_ntohs(ip_header_ptr->LENGTH) - iplen; /* Get TCP header */ transport.PTR = TRANSPORT_PTR(ip_header_ptr); mqx_htons(transport.TCP_PTR->checksum, 0); /* Clear checksum field */ protocol = mqx_ntohc(ip_header_ptr->PROTOCOL); /* PROTOCOL */ checksum = (uint16_t) _mem_sum_ip(protocol, 8, ip_header_ptr->SOURCE); /* IP SRC and DST ADDR */ checksum = (uint16_t) _mem_sum_ip(checksum, len, transport.PTR); /* TCP LENGTH */ checksum = IP_Sum_immediate(checksum, len); checksum = IP_Sum_invert(checksum); mqx_htons(transport.TCP_PTR->checksum, checksum); } /* Endbody */
DNAT_RULE_STRUCT_PTR DNAT_lookup_rule ( NAT_CFG_STRUCT_PTR nat_cfg_ptr, IP_HEADER_PTR ip_header_ptr, bool pub_to_prv ) { /* Body */ TRANSPORT_UNION transport; DNAT_ELEMENT_STRUCT_PTR element_ptr; _ip_address source_ip = mqx_ntohl(ip_header_ptr->SOURCE); uint32_t ip_protocol; uint16_t source_port, destination_port; /* source port and destination port */ transport.PTR = TRANSPORT_PTR(ip_header_ptr); ip_protocol = mqx_ntohc(ip_header_ptr->PROTOCOL); /* NAT spports ICMP, UDP and TCP transport layer protocols */ switch (ip_protocol) { case IPPROTO_TCP: destination_port = mqx_ntohs(transport.TCP_PTR->dest_port); source_port = mqx_ntohs(transport.TCP_PTR->source_port); break; case IPPROTO_UDP: destination_port = mqx_ntohs(transport.UDP_PTR->DEST_PORT); source_port = mqx_ntohs(transport.UDP_PTR->SRC_PORT); break; case IPPROTO_ICMP: /* Allow all ICMP request/reply */ return NULL; } /* Endswitch */ element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE); /* ** Check for the target port and then forward the packet to the corresponding ** DNAT rule target ip. */ while (element_ptr != NULL) { if (element_ptr->RULE.IP_PROTOCOL == ip_protocol) { if (pub_to_prv) { if ((destination_port >= element_ptr->RULE.PUBLIC_START_PORT) && (destination_port <= element_ptr->RULE.PUBLIC_END_PORT)) { break; } } else { if ((source_ip == element_ptr->RULE.PRIVATE_IP) && (source_port >= element_ptr->RULE.PRIVATE_START_PORT) && (source_port <= element_ptr->RULE.PRIVATE_END_PORT)) { break; } } } element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_next(&nat_cfg_ptr->RULE_QUEUE, &element_ptr->ELEMENT); } /* Endwhile */ if (element_ptr!=NULL) { return &element_ptr->RULE; } else { return NULL; } }/* Endbody */
uint_32 NAT_ALG_tftp_apply ( RTCSPCB_PTR _PTR_ pcb_ptr_ptr, /* [IN/OUT] PCB containing packet */ boolean pub_to_prv, /* [IN] Direction of packet */ pointer alg_cfg_ptr, /* [IN] Pointer to TFTP config */ pointer _PTR_ session_ptr_ptr /* [OUT] Pointer to session */ ) { /* Body */ NAT_SESSION_STRUCT_PTR nat_session_ptr = *((NAT_SESSION_STRUCT_PTR *)session_ptr_ptr); uchar_ptr data_ptr = (pointer)RTCSPCB_DATA(*pcb_ptr_ptr); IP_HEADER_PTR ip_header_ptr = (IP_HEADER_PTR)(pointer)data_ptr; TRANSPORT_UNION transport; TFTP_HEADER_PTR tftp_header_ptr; uint_16 opcode, block; if (nat_session_ptr == NULL) { return RTCS_OK; } /* Endif */ /* TFTP uses UDP */ if (ntohc(ip_header_ptr->PROTOCOL) != IPPROTO_UDP) { return RTCS_OK; } /* Endif */ transport.PTR = TRANSPORT_PTR(ip_header_ptr); /* The UDP length should be long enough to contain a TFTP header */ if (ntohs(transport.UDP_PTR->LENGTH) < sizeof(UDP_HEADER) + sizeof(TFTP_HEADER)) { return RTCS_OK; } /* Endif */ tftp_header_ptr = (TFTP_HEADER_PTR)(pointer)(transport.UDP_PTR + 1); opcode = ntohs(tftp_header_ptr->OP); block = ntohs(tftp_header_ptr->BLOCK); /* ** A normal reply should have: OP 3 (DATA) and BLOCK 1 (first block) or ** an OP 4 and BLOCK 0. Error replies should have: OP 5, and a variable ** error code */ if ((opcode != 3 || block != 1) && (opcode != 4 || block != 0) && (opcode != 5)) { return RTCS_OK; } /* Endif */ if (nat_session_ptr->SNAT_OR_DNAT == SNAT) { /* We only need to consider the first packet returned by the server */ if (!pub_to_prv) { return RTCS_OK; } /* Endif */ /* Make sure port number is the TFTP port number */ if (nat_session_ptr->PUB_PORT != IPPORT_TFTP) { return RTCS_OK; } /* Endif */ /* Set new server port number */ nat_session_ptr->PUB_PORT = ntohs(transport.UDP_PTR->SRC_PORT); } else { /* We only need to consider the first packet returned by the server */ if (pub_to_prv){ return RTCS_OK; } /* Endif */ /* Make sure port number is the TFTP port number */ if (nat_session_ptr->PRV_PORT != IPPORT_TFTP) { return RTCS_OK; } /* Endif */ /* Set new server port number */ nat_session_ptr->PRV_PORT = ntohs(transport.UDP_PTR->SRC_PORT); } /* Endif */ return RTCS_OK; } /* Endbody */