📄 natpptpptalg.c
字号:
/* natPPTPPTAlg.c *//* Copyright 2002-2003 Wind River Systems, Inc. *//* @format.tab-size 4, @format.use-tabs true, @format.new-line lf *//* WindNet NAT "installable" PPTP Pass-Thru Application Level Gateway (ALG) *//*modification history--------------------01f,16jul03,zhu fixed ntohs problem for peer id01e,18jun03,myz Fixed the problem of incorrectly converting IP length field.01d,21may03,zhu Fixed issues with little Endian operation01c,28apr03,myz fixed diab compiler warnings01b,25apr03,myz replaced taskSpawn with NAT event utility to create timer.01a,23apr03,zhu Updated.050802 mdg Created.*//*#define PPTP_PT_DEBUG*//* ANSI headers */#include <stdio.h> /* printf */#include <string.h> /* memset *//* VxWorks headers */#include <in.h> #include <ioLib.h>#include <sysLib.h>#include <taskLib.h>/* NAT-specific headers */#include <nat/natAlgApi.h>#include "nat.h" #include "natPPTPPTAlg.h"#include "nat_packet_structures.h"static const char* pptp_gre_alg_desc = "WindNet NAT - PPTP GRE Pass-Thru ALG v1.0 - Copyright 2002-2003 Wind River Systems, Inc.";static const char* pptp_gre_alg_name = "PPTP GRE PT ALG";static const char* pptp_control_alg_desc = "WindNet NAT - PPTP Control Pass-Thru ALG v1.0 - Copyright 2002-2003 Wind River Systems, Inc.";static const char* pptp_control_alg_name = "PPTP Control PT ALG";#define PPTP_GRE_VERSION 1#define PPTP_GRE_PROTOCOL 0x880B#define PPTP_CONTROL_PACKET_TYPE 1#define PPTP_MAGIC_COOKIE 0x1a2b3c4d#define PPTP_NATED_CLIENT_TIMEOUT 30*60#define PPTP_NATED_SERVER_TIMEOUT 2*60#define PPTP_DATA_INIT_TIMEOUT 2*60#define PPTP_QUICK_TIMEOUT 30/* Constants used to generate spoofed call ids for outgoing translation */#define LOWER_SPOOFED_CALL_ID_VALUE 0x8000#define UPPER_SPOOFED_CALL_ID_VALUE 0xFFFE#define FAKE_SPOOFED_CALL_ID_MASK 0x7FFFstatic NAT_ID_INFO nat_id;static NAT_AGENT_INFO pptp_gre_agent_info;static NAT_AGENT_INFO pptp_control_agent_info;static PPTP_TRANSLATION_HEADER pptp_translation_list;static SEM_ID pptpListLock;static USHORT next_pptp_spoofed_call_id;static void * pptpTimerId;LOCAL PPTP_TRANSLATION_ENTRY *new_pptp_translation_entry ( PPTP_TRANSLATION_HEADER *sptr_pptp_translation_list, USHORT call_id, USHORT spoofed_call_id, BOOL nated_client, IP_ADDRESS local_address, IP_ADDRESS remote_address);LOCAL PPTP_TRANSLATION_ENTRY *find_outbound_pptp_entry_peer ( IP_ADDRESS local_address, IP_ADDRESS remote_address, USHORT call_id, PPTP_TRANSLATION_HEADER *sptr_pptp_translation_list);LOCAL PPTP_TRANSLATION_ENTRY *find_outbound_pptp_entry ( IP_ADDRESS local_address, IP_ADDRESS remote_address, USHORT call_id, PPTP_TRANSLATION_HEADER *sptr_pptp_translation_list);LOCAL PPTP_TRANSLATION_ENTRY *find_inbound_pptp_entry ( IP_ADDRESS remote_address, USHORT call_id, PPTP_TRANSLATION_HEADER *sptr_pptp_translation_list);LOCAL USHORT new_spoofed_call_id();LOCAL void nat_pptp_timer (void);LOCAL void check_pptp_translation_entry_timer ( PPTP_TRANSLATION_HEADER *sptr_pptp_translation_list);LOCAL void clear_pptp_translation_entry_list (PPTP_TRANSLATION_HEADER *sptr_pptp_translation_list);/*****************************************************************************************Function: natPPTPGREPacketDescription: ******************************************************************************************/BOOL natPPTPGREPacket(u_long nat_id, u_long agent_id, u_long session_id, NAT_DIRECTION direction, void* packet){ PPTP_GRE_PACKET *sptr_pptp_gre_packet = (PPTP_GRE_PACKET*)packet; PPTP_TRANSLATION_ENTRY *sptr_pptp_translation_entry; IP_ADDRESS address; USHORT checksum; USHORT flags; PPTP_GRE_V2_MESSAGE_HEADER_FLAGS *bit_flags; /* If it's not long enough to full GRE header, give up... * The length field is already converted to the host byte order */ if ((int)((UINT32)(sptr_pptp_gre_packet->ip_header.total_length) - (sptr_pptp_gre_packet->ip_header.version_header_length.header_length * 4) - 8) < 0) return FALSE; flags = *(USHORT *) &sptr_pptp_gre_packet->bit_flags; flags = ntohs(flags); bit_flags = (PPTP_GRE_V2_MESSAGE_HEADER_FLAGS *) &flags; /* If it isn't the a PPTP GRE packet, give up..... */ if (bit_flags->version != PPTP_GRE_VERSION || ntohs(sptr_pptp_gre_packet->protocol_type) != PPTP_GRE_PROTOCOL) return FALSE; if (direction == NAT_OUTBOUND) { /* Try to find translation entry */ sptr_pptp_translation_entry = find_outbound_pptp_entry_peer(ntohl(sptr_pptp_gre_packet->ip_header.source_address), ntohl(sptr_pptp_gre_packet->ip_header.destination_address), ntohs(sptr_pptp_gre_packet->call_id), &pptp_translation_list); /* No entry found, create a new one */ if (sptr_pptp_translation_entry == NULL) { sptr_pptp_translation_entry = new_pptp_translation_entry(&pptp_translation_list, ntohs(sptr_pptp_gre_packet->call_id), ntohl(sptr_pptp_gre_packet->ip_header.destination_address) & FAKE_SPOOFED_CALL_ID_MASK, FALSE, ntohl(sptr_pptp_gre_packet->ip_header.source_address), ntohl(sptr_pptp_gre_packet->ip_header.destination_address)); } if (sptr_pptp_translation_entry->nated_client) sptr_pptp_translation_entry->pptp_translation_entry_timer = PPTP_NATED_CLIENT_TIMEOUT; else sptr_pptp_translation_entry->pptp_translation_entry_timer = PPTP_NATED_SERVER_TIMEOUT; /* Translate the source address */ checksum = sptr_pptp_gre_packet->ip_header.header_checksum; address = htonl (nat.global_address); checksum_fixup ((BYTE *) &checksum, (BYTE *) &sptr_pptp_gre_packet->ip_header.source_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); sptr_pptp_gre_packet->ip_header.source_address = address; sptr_pptp_gre_packet->ip_header.header_checksum = checksum; return(TRUE); } else { /* Try to find translation entry */ sptr_pptp_translation_entry = find_inbound_pptp_entry(ntohl(sptr_pptp_gre_packet->ip_header.source_address), ntohs(sptr_pptp_gre_packet->call_id), &pptp_translation_list); /* No entry found....toss it */ if (sptr_pptp_translation_entry == NULL) { return(FALSE); } if (sptr_pptp_translation_entry->nated_client) { sptr_pptp_translation_entry->pptp_translation_entry_timer = PPTP_NATED_CLIENT_TIMEOUT; sptr_pptp_gre_packet->call_id = htons(sptr_pptp_translation_entry->call_id); } else sptr_pptp_translation_entry->pptp_translation_entry_timer = PPTP_NATED_SERVER_TIMEOUT; /* Translate the destination address.... */ address = htonl(sptr_pptp_translation_entry->local_address); checksum_fixup ((BYTE *) &checksum, (BYTE *) &sptr_pptp_gre_packet->ip_header.destination_address, sizeof (IP_ADDRESS), (BYTE *) &address, sizeof (IP_ADDRESS)); sptr_pptp_gre_packet->ip_header.destination_address = address; sptr_pptp_gre_packet->ip_header.header_checksum = checksum; return(TRUE); }}/*****************************************************************************************Function: natPPTPControPacketDescription: ******************************************************************************************/BOOL natPPTPControlPacket(u_long nat_id, u_long agent_id, u_long session_id, NAT_DIRECTION direction, void* packet){ PPTP_TRANSLATION_ENTRY *sptr_pptp_translation_entry; PPTP_CONTROL_PACKET *sptr_pptp_control_packet = (PPTP_CONTROL_PACKET *) packet; USHORT *call_id,*peers_call_id; USHORT spoofed_call_id; NAT_BIND_INFO bind_info; NAT_BIND_SESSION session; USHORT msg; NAT_STATUS status; USHORT new_call_id; /* If it's not long enough to have TCP data, give up.... * The length field is already converted to the host byte order */ if ((int)((UINT32)(sptr_pptp_control_packet->ip_header.total_length) - (sptr_pptp_control_packet->ip_header.version_header_length.header_length * 4) - sizeof(TCP_HEADER) - sizeof(PPTP_MESSAGE_HEADER) - sizeof(PPTP_CONTROL_MESSAGE_HEADER)) < 0) return TRUE; /* If it isn't a PPTP Control packet, give up..... */ if (ntohs(sptr_pptp_control_packet->pptp_header.type) != PPTP_CONTROL_PACKET_TYPE || ntohl(sptr_pptp_control_packet->pptp_header.magic_cookie) != PPTP_MAGIC_COOKIE) return TRUE; msg = ntohs(sptr_pptp_control_packet->control_header.message_type); if (direction == NAT_OUTBOUND) { /* call natGetTransportBind to get the pointer to the TCP translation entry */ session.protocol = IPPROTO_TCP; session.local_addr = 0; session.local_transport = 0; session.global_addr = ntohl(sptr_pptp_control_packet->ip_header.source_address); session.global_transport = ntohs(sptr_pptp_control_packet->tcp_header.source_port); session.remote_addr = ntohl(sptr_pptp_control_packet->ip_header.destination_address); session.remote_transport = ntohs(sptr_pptp_control_packet->tcp_header.destination_port); if ((status = natGetTransportBind((u_long)&nat, &session, &bind_info, NAT_BIND_FULL)) != NAT_OK) return(FALSE); if (msg == PPTP_OUT_CALL_REQUEST || msg == PPTP_IN_CALL_REQUEST) { if (msg == PPTP_OUT_CALL_REQUEST) call_id = &sptr_pptp_control_packet->message.outgoing_call_request.call_id; else call_id = &sptr_pptp_control_packet->message.incoming_call_request.call_id; /* Create a new spoofed call id to use instead of the client's ID */ spoofed_call_id = new_spoofed_call_id(); sptr_pptp_translation_entry = new_pptp_translation_entry (&pptp_translation_list, ntohs(*call_id), spoofed_call_id, TRUE, bind_info.local_addr, ntohl(sptr_pptp_control_packet->ip_header.destination_address)); /* Put the spoofed ID in the message and set the initial timeout... */ if (sptr_pptp_translation_entry != NULL) { sptr_pptp_translation_entry->pptp_translation_entry_timer = PPTP_DATA_INIT_TIMEOUT; spoofed_call_id = htons(spoofed_call_id); checksum_fixup ((BYTE *) &sptr_pptp_control_packet->tcp_header.checksum, (BYTE *) call_id, sizeof (USHORT), (BYTE *) &spoofed_call_id, sizeof (USHORT)); *call_id = spoofed_call_id; } return(TRUE); } else if (msg == PPTP_CALL_CLEAR_REQUEST || msg == PPTP_CALL_DISCONNECT_NOTIFY) { /* Get the call ID from the message and find the translation entry */ if (msg == PPTP_CALL_CLEAR_REQUEST) { spoofed_call_id = ntohs(sptr_pptp_control_packet->message.call_clear_request.call_id); call_id = &sptr_pptp_control_packet->message.call_clear_request.call_id; } else { spoofed_call_id = ntohs(sptr_pptp_control_packet->message.call_disconnect_notify.call_id); call_id = &sptr_pptp_control_packet->message.call_disconnect_notify.call_id; } sptr_pptp_translation_entry =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -