📄 natipsecptalg.c
字号:
/* natIPSecPTAlg.c *//* Copyright 2002-2003 Wind River Systems, Inc. *//* @format.tab-size 4, @format.use-tabs true, @format.new-line lf *//* WindNet NAT "installable" IPSec Pass-Thru Application Level Gateway (ALG) *//*modification history--------------------01e,24jul03,zhu fixed endianess problem01d,23jul03,zhu fixed the crash problem by ESP_GUESS_SIZE01c,28apr03,myz fixed diab compiler warnings on some archs. 01b,25apr03,myz replaced taskSpawn with NAT event utility to create timer.01a,23apr03,zhu Updated.050102 mdg Created.*//*#define IPSEC_PT_DEBUG*//* ANSI headers */#include <stdio.h> /* printf */#include <string.h> /* memset *//* VxWorks headers */#include <in.h> /* IPPROTO_TCP */#include <ioLib.h>#include <sockLib.h>#include <sysLib.h>#include <taskLib.h>/* NAT-specific headers */#include <nat/natAlgApi.h>#include "nat.h" /* IP_ADDRESS */#include "natIPSecPTAlg.h"#include "nat_packet_structures.h"static const char* isakmp_alg_desc = "WindNet NAT - ISAKMP IPSec Pass-Thru ALG v1.0 - Copyright 2002-2003 Wind River Systems, Inc.";static const char* isakmp_alg_name = "ISAKMP PT ALG";static const char* esp_alg_desc = "WindNet NAT - ESP IPSec Pass-Thru ALG v1.0 - Copyright 2002-2003 Wind River Systems, Inc.";static const char* esp_alg_name = "ESP PT ALG";#define ISAKMP_INIT_TIMEOUT 2*60#define ISAKMP_ESTABLISHED_TIMEOUT 15*60#define ISAKMP_OLD_TIMEOUT 5*60#define ESP_INIT_TIMEOUT 2*60#define ESP_ESTABLISHED_TIMEOUT 15*60#define ESP_SQUELCHED_TIMEOUT 30#define IPSEC_INIT_MAX_RETRIES 5#define ESP_GUESS_SIZE 5static NAT_ID_INFO nat_id;static NAT_AGENT_INFO isakmp_agent_info;static NAT_AGENT_INFO esp_agent_info;static ISAKMP_TRANSLATION_HEADER isakmp_translation_list;static ESP_TRANSLATION_HEADER esp_translation_list;static SEM_ID isakmpListLock;static SEM_ID espListLock;static int espRawFd;static void * ipSecTimerId;LOCAL ISAKMP_TRANSLATION_ENTRY *match_outbound_cookies_with_isakmp_entry ( ULONG64 initiator_cookie, ULONG64 responder_cookie, IP_ADDRESS local_address, IP_ADDRESS remote_address, ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list);LOCAL ISAKMP_TRANSLATION_ENTRY *match_inbound_cookies_with_isakmp_entry ( ULONG64 initiator_cookie, ULONG64 responder_cookie, IP_ADDRESS remote_address, ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list);LOCAL ISAKMP_TRANSLATION_ENTRY *new_isakmp_translation_entry ( ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list, ULONG64 initiator_cookie, ULONG64 responder_cookie, IP_ADDRESS local_address, IP_ADDRESS remote_address);LOCAL ULONG find_active_isakmp_entries ( IP_ADDRESS remote_address, IP_ADDRESS *active_address, ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list);LOCAL void *cleanup_isakmp_list ( ULONG64 initiator_cookie, ULONG64 responder_cookie, IP_ADDRESS local_address, IP_ADDRESS remote_address, ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list);LOCAL ESP_TRANSLATION_ENTRY *match_outbound_spi_with_esp_entry ( ULONG outbound_spi, IP_ADDRESS local_address, IP_ADDRESS remote_address, ESP_TRANSLATION_HEADER *sptr_esp_translation_list);LOCAL ESP_TRANSLATION_ENTRY *match_inbound_spi_with_esp_entry ( ULONG inbound_spi, IP_ADDRESS remote_address, ESP_TRANSLATION_HEADER *sptr_esp_translation_list);LOCAL ESP_TRANSLATION_ENTRY *find_pending_esp_entry ( IP_ADDRESS remote_address, ESP_TRANSLATION_HEADER *sptr_esp_translation_list);LOCAL ESP_TRANSLATION_ENTRY *new_esp_translation_entry ( ESP_TRANSLATION_HEADER *sptr_esp_translation_list, ULONG outbound_spi, IP_ADDRESS local_address, IP_ADDRESS remote_address);LOCAL void nat_ipsec_timer (void);LOCAL void check_isakmp_translation_entry_timer ( ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list);LOCAL void check_esp_translation_entry_timer ( ESP_TRANSLATION_HEADER *sptr_esp_translation_list);LOCAL void clear_isakmp_translation_entry_list (ISAKMP_TRANSLATION_HEADER *sptr_isakmp_translation_list);LOCAL void clear_esp_translation_entry_list (ESP_TRANSLATION_HEADER *sptr_esp_translation_list);/*****************************************************************************************Function: natIsakmpPacketDescription: ******************************************************************************************/BOOL natIsakmpPacket(u_long nat_id, u_long agent_id, u_long session_id, NAT_DIRECTION direction, void* packet){ ISAKMP_PACKET *sptr_isakmp_packet = (ISAKMP_PACKET*)packet; ISAKMP_TRANSLATION_ENTRY *sptr_isakmp_translation_entry; IP_ADDRESS address; USHORT checksum; /* If it's not long enough to contain cookies, give up... */ if ((ntohl(sptr_isakmp_packet->ip_header.total_length) - (sptr_isakmp_packet->ip_header.version_header_length.header_length * 4) - sizeof(struct UDP_HEADER)) < 16) return FALSE; /* If the initiator cookie is zero, give up... */ if (sptr_isakmp_packet->initiator_cookie == 0) return FALSE; if (direction == NAT_OUTBOUND) { /* Try to find translation entry, with both initiator and responder cookie */ sptr_isakmp_translation_entry = match_outbound_cookies_with_isakmp_entry(ntoh64(sptr_isakmp_packet->initiator_cookie), ntoh64(sptr_isakmp_packet->responder_cookie), ntohl(sptr_isakmp_packet->ip_header.source_address) , ntohl(sptr_isakmp_packet->ip_header.destination_address) , &isakmp_translation_list); /* If not found, try without responder cookie */ if (sptr_isakmp_translation_entry == NULL) sptr_isakmp_translation_entry = match_outbound_cookies_with_isakmp_entry(ntoh64(sptr_isakmp_packet->initiator_cookie), 0, ntohl(sptr_isakmp_packet->ip_header.source_address) , ntohl(sptr_isakmp_packet->ip_header.destination_address) , &isakmp_translation_list); /* No entry found, create a new one */ if (sptr_isakmp_translation_entry == NULL) { sptr_isakmp_translation_entry = new_isakmp_translation_entry(&isakmp_translation_list, ntoh64(sptr_isakmp_packet->initiator_cookie), ntoh64(sptr_isakmp_packet->responder_cookie), ntohl(sptr_isakmp_packet->ip_header.source_address), ntohl(sptr_isakmp_packet->ip_header.destination_address)); if (sptr_isakmp_translation_entry == NULL) return(FALSE); } /* Reset the translation entry timer */ if (sptr_isakmp_translation_entry->responder_cookie == 0) sptr_isakmp_translation_entry->isakmp_translation_entry_timer = ISAKMP_INIT_TIMEOUT; else sptr_isakmp_translation_entry->isakmp_translation_entry_timer = ISAKMP_ESTABLISHED_TIMEOUT; /* Translate the source address */ address = htonl (nat.global_address); checksum_fixup ((BYTE *) &sptr_isakmp_packet->header.checksum, (BYTE *) &sptr_isakmp_packet->ip_header.source_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); checksum = sptr_isakmp_packet->ip_header.header_checksum; checksum_fixup ((BYTE *) &checksum, (BYTE *) &sptr_isakmp_packet->ip_header.source_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); sptr_isakmp_packet->ip_header.source_address = address; sptr_isakmp_packet->ip_header.header_checksum = checksum; return(TRUE); } else { /* Try to find translation entry, with both initiator and responder cookie */ sptr_isakmp_translation_entry = match_inbound_cookies_with_isakmp_entry(ntoh64(sptr_isakmp_packet->initiator_cookie), ntoh64(sptr_isakmp_packet->responder_cookie), ntohl(sptr_isakmp_packet->ip_header.source_address) , &isakmp_translation_list); /* If not found, try without responder cookie */ if (sptr_isakmp_translation_entry == NULL) sptr_isakmp_translation_entry = match_inbound_cookies_with_isakmp_entry(ntoh64(sptr_isakmp_packet->initiator_cookie), 0, ntohl(sptr_isakmp_packet->ip_header.source_address) , &isakmp_translation_list); /* No entry found, drop packet */ if (sptr_isakmp_translation_entry == NULL) return(FALSE); /* Save the responder cookie if needed */ if (sptr_isakmp_translation_entry->responder_cookie == 0) sptr_isakmp_translation_entry->responder_cookie = ntoh64(sptr_isakmp_packet->responder_cookie); cleanup_isakmp_list(ntoh64(sptr_isakmp_packet->initiator_cookie), ntoh64(sptr_isakmp_packet->responder_cookie), sptr_isakmp_translation_entry->local_address, ntohl(sptr_isakmp_packet->ip_header.source_address), &isakmp_translation_list); /* Reset the translation entry timer */ sptr_isakmp_translation_entry->isakmp_translation_entry_timer = ISAKMP_ESTABLISHED_TIMEOUT; /* Translate the destination address.... */ address = htonl (sptr_isakmp_translation_entry->local_address); checksum_fixup ((BYTE *) &sptr_isakmp_packet->header.checksum, (BYTE *) &sptr_isakmp_packet->ip_header.destination_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); checksum = sptr_isakmp_packet->ip_header.header_checksum; checksum_fixup ((BYTE *) &checksum, (BYTE *) &sptr_isakmp_packet->ip_header.destination_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); sptr_isakmp_packet->ip_header.destination_address = address; sptr_isakmp_packet->ip_header.header_checksum = checksum; return(TRUE); }}/*****************************************************************************************Function: natEspPacketDescription: ******************************************************************************************/BOOL natEspPacket(u_long nat_id, u_long agent_id, u_long session_id, NAT_DIRECTION direction, void* packet){ ESP_PACKET *sptr_esp_packet = (ESP_PACKET*)packet; ESP_TRANSLATION_ENTRY *sptr_esp_translation_entry; IP_ADDRESS address; USHORT checksum; IP_ADDRESS guess_ip[ESP_GUESS_SIZE]; struct sockaddr_in to; ULONG i,num_active_isakmp; int num_sent; if (direction == NAT_OUTBOUND) { ULONG spi; ULONG srcAddr; ULONG dstAddr; /* Try to find translation entry, with both initiator and responder cookie */ spi = sptr_esp_packet->spi; srcAddr = sptr_esp_packet->ip_header.source_address; dstAddr = sptr_esp_packet->ip_header.destination_address; spi = ntohl(spi); srcAddr = ntohl(srcAddr); dstAddr = ntohl(dstAddr); sptr_esp_translation_entry = match_outbound_spi_with_esp_entry(spi, srcAddr, dstAddr, &esp_translation_list); /* No entry found, maybe create a new one */ if (sptr_esp_translation_entry == NULL) { if (((sptr_esp_translation_entry = find_pending_esp_entry(dstAddr, &esp_translation_list)) != NULL) && !sptr_esp_translation_entry->squelched) { /* Found one in progress to same host....need to wait awhile */ sptr_esp_translation_entry->blocking = TRUE; sptr_esp_translation_entry->esp_translation_entry_timer = ESP_INIT_TIMEOUT; nat_printf (NAT_PRINTF_TRACE, "Blocked ESP Packet Dropped from local host %08lx\n", ntohl(sptr_esp_packet->ip_header.source_address)); return(FALSE); } else { /* Create a new entry, no others in progress to same host... */ sptr_esp_translation_entry = new_esp_translation_entry(&esp_translation_list, spi, srcAddr, dstAddr ); if (sptr_esp_translation_entry == NULL) return(FALSE); sptr_esp_translation_entry->esp_translation_entry_timer = ESP_INIT_TIMEOUT; } } else { if (sptr_esp_translation_entry->squelched) { nat_printf (NAT_PRINTF_TRACE, "Squelched ESP Packet Dropped from local host %08lx\n", ntohl(sptr_esp_packet->ip_header.source_address)); return(FALSE); } /* The remote end hasn't responded yet.... */ if (sptr_esp_translation_entry->inbound_spi == 0) { sptr_esp_translation_entry->esp_translation_entry_timer = ESP_INIT_TIMEOUT; if (sptr_esp_translation_entry->blocking) { sptr_esp_translation_entry->outbound_retry_count++; nat_printf(NAT_PRINTF_TRACE,"ESP Outbound Retry Count = %d on local host %08lx\n", sptr_esp_translation_entry->outbound_retry_count, ntohl(sptr_esp_packet->ip_header.source_address)); if (sptr_esp_translation_entry->outbound_retry_count > IPSEC_INIT_MAX_RETRIES) { sptr_esp_translation_entry->squelched = TRUE; sptr_esp_translation_entry->esp_translation_entry_timer = ESP_SQUELCHED_TIMEOUT; nat_printf (NAT_PRINTF_TRACE, "Squelched ESP Packet Dropped from local host %08lx\n", ntohl(sptr_esp_packet->ip_header.source_address)); return(FALSE); } } } } /* Translate the source address */ checksum = sptr_esp_packet->ip_header.header_checksum; address = htonl (nat.global_address); checksum_fixup ((BYTE *) &checksum, (BYTE *) &sptr_esp_packet->ip_header.source_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); sptr_esp_packet->ip_header.source_address = address; sptr_esp_packet->ip_header.header_checksum = checksum; return(TRUE); } else { /* Try to find translation entry, with both initiator and responder cookie */ sptr_esp_translation_entry = match_inbound_spi_with_esp_entry(ntohl(sptr_esp_packet->spi), ntohl(sptr_esp_packet->ip_header.source_address) , &esp_translation_list); /* If not found, try pending entry */ if (sptr_esp_translation_entry == NULL) sptr_esp_translation_entry = find_pending_esp_entry(ntohl(sptr_esp_packet->ip_header.source_address) , &esp_translation_list); /* No entry found, try to guess who should get the packet based on ISAKMP traffic */ if (sptr_esp_translation_entry == NULL) { num_active_isakmp = find_active_isakmp_entries(ntohl(sptr_esp_packet->ip_header.source_address), guess_ip, &isakmp_translation_list); /* Send the packet to all of the possible destinations */ for (i=0;i<num_active_isakmp;i++) { sptr_esp_packet->ip_header.destination_address = htonl(guess_ip[i]); to.sin_family = AF_INET; to.sin_addr.s_addr = guess_ip[i]; num_sent = sendto(espRawFd, (char *)sptr_esp_packet, ntohs(sptr_esp_packet->ip_header.total_length), 0,(struct sockaddr *) &to,sizeof(struct sockaddr_in)); } return(FALSE); } /* Save the inbound si if needed */ if (sptr_esp_translation_entry->inbound_spi == 0) sptr_esp_translation_entry->inbound_spi = ntohl(sptr_esp_packet->spi);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -