📄 natalgapi.c
字号:
/* natAlgApi.c - WIND NET NAT Application Gateway (ALG) programming interface */
/* WIND NET NAT Application Level Gateway (ALG) Application Programming Interface */
/* Copyright 2000-2004 Wind River Systems, Inc. */
/* @format.tab-size 4, @format.use-tabs true, @format.new-line lf */
/*
modification history
--------------------
01d,01mar04,svk updated library description for refgen
01c,29aug03,zhu updated the format for refgen
01b,13aug03,zhu fixed natSetBind memory leak
01a,23apr03,zhu enhanced natBindShow
041103 vks removed #ifdef'd out code under natFreeSession, natSetSession and natFreeBundle
040903 vks updated Copyright info
032603 vks replaced rw_container with lstLib (for bind_list)
111302 vvv added semGive on error in natSetBind (SPR #79394)
092402 vvv replaced references to rw_container with direct linked list
access to improve performance
101901 tk Fix data type to avoid warning in T3 compiler.
100301 tk Remove semaphore calls. They have been moved to nat_api.c.
092101 tk Modify natGetTransportBind() to check for remote address and
port or just remote address.
080701 tk Modified natSetBind for H.323 protocol support.
070201 tk Enhance natSetBind, natFreeBind, natGetAddrBind,
natGetTransportBind, and natBindShow. Now natSetBind/
natFreeBind actually create/delete an entry to/from the
protocol translation list in the NAT core in addition to
adding/deleting the entry in its own bind list.
060501 tk Add a static function match_nat_agent().
060401 tk Add a new API function natUnregisterAgent().
*/
/*
DESCRIPTION
This library supplies an API for integrating a new ALG with
WIND NET NAT. See also the timer API supplied by 'natEvtTimer'.
SEE ALSO
'natInit'
*/
#include <stdio.h> /* printf */
#include "nat.h"
#include "nat_api.h"
/*
#define ALG_DEBUG
*/
/*****************************************************************************
This utility function is called by the API functions to verify for the
the validity of the external agent (i.e. if it is a registered agent)
*****************************************************************************/
static NAT_STATUS match_nat_agent(u_long nat_id, u_long agent_id)
{
NAT_CLASS *nat_p;
NAT_AGENT_INFO* agent_info;
if (agent_id == 0)
{
return (NAT_OK); /* agent is NAT */
}
nat_p = (NAT_CLASS *) nat_id;
semTake(agentListLock, WAIT_FOREVER);
agent_info = (NAT_AGENT_INFO *) lstFirst(&nat.agent_list);
while (agent_info != NULL)
{
if (agent_info->id == agent_id)
{
semGive (agentListLock);
return (NAT_OK);
}
agent_info = (NAT_AGENT_INFO *) lstNext((NODE*) agent_info);
}
semGive(agentListLock);
return (NAT_INVALID_AGENT_ID);
}
/****************************************************************************/
/****************************************************************************/
/* Initial entry point for an external NAT agent (ALG, Back-up NAT, etc) */
/****************************************************************************/
/*****************************************************************************
Function: natGetID
Description:
This function is called by the external agent to obtain the NAT service
identifier and its type. The external agent is responsible
for allocating the NAT_ID_INFO data structure and pass its pointer as the
argument to this function. NAT fills in the structure including the NAT ID.
*****************************************************************************/
/******************************************************************************
*
* natGetID - get a NAT service identifier
*
* The external agent calls this external agent to obtain the NAT service
* identifier and its type. The external agent is responsible for allocating
* the NAT_ID_INFO data structure and passing its pointer as the argument to
* this routine. NAT fills in the structure including the NAT ID.
*
* Currently, WIND NET NAT supports only a single instance of NAT. The
* supported types are NAPT or Basic NAT (see RFC 2663 for explanations of
* the different flavors of NAT).
*
* RETURNS
*
* NAT_OK, if successful; or NAT_INVALID_ARG_PTR, if <id_info> is NULL.
*
*/
NAT_STATUS natGetID
(
NAT_ID_INFO* id_info /* Output area for NAT service information. */
)
{
if (id_info == NULL)
{
return(NAT_INVALID_ARG_PTR);
}
id_info->id = (u_long)&nat; /* A global variable that may go away some day */
id_info->enabled = nat.enabled;
id_info->type = 0;
if(nat.single_global_address_enabled == TRUE)
{
id_info->type |= NAT_TYPE_NAPT;
}
else
{
id_info->type |= NAT_TYPE_BASIC;
}
return(NAT_OK);
}
/*****************************************************************************
Function: natRegisterAgent
Description:
This function is called by the external agent to register with the NAT service.
The external agent allocates the NAT_AGENT_INFO storage and fill in the agent's
information before passing it to the function. Upon successful completion of
this function, NAT will assign and return the agent ID (i.e. handle) in the
NAT_AGENT_INFO data structure.
*****************************************************************************/
/******************************************************************************
*
* natRegisterAgent - register external agent with NAT service
*
* The external agent calls this routine to register with the NAT service.
* Before calling this function, the external agent allocates the
* NAT_AGENT_INFO structure and fills in the agent's information before passing
* it to the routine. Typical agent information includes the following:
* \ml
* \m -
* agent type (currently it can only be ALG)
* \m -
* whether the agent chooses to translate addresses in the IP and TCP/UDP
* headers as well as in the payload (no NAT translation), or only in the
* payload (post-NAT translation)
* \m -
* agent's port number
* \m -
* callback functions
* \me
* Upon successful completion of this routine, NAT assigns and returns the
* agent ID (the handle) in the NAT_AGENT_INFO data structure.
*
* RETURNS
*
* \is
* \i NAT_OK
* Success.
* \i NAT_INVALID_NAT_ID
* Invalid NAT ID.
* \i NAT_INVALID_ARG_PTR
* Invalid pointer to agent information.
* \i NAT_UNSUPPORTED_AGENT_TYPE
* Requested agent type not is supported.
* \i NAT_SYSTEM_ERROR
* Cannot allocate storage for the new agent.
* \ie
*
*/
NAT_STATUS natRegisterAgent
(
u_long nat_id, /* NAT service ID, from a natGetID() call. */
NAT_AGENT_INFO* agent_info /* Pointer to agent information. */
)
{
NAT_CLASS* nat_p;
NAT_AGENT_INFO* new_agent_info;
if (nat_id == 0)
{
return(NAT_INVALID_NAT_ID);
}
nat_p = (NAT_CLASS*) nat_id;
if (agent_info == NULL)
{
return(NAT_INVALID_ARG_PTR);
}
if (agent_info->type != NAT_AGENT_TYPE_ALG)
{
return(NAT_UNSUPPORTED_AGENT_TYPE);
}
new_agent_info = (NAT_AGENT_INFO*) malloc (sizeof (NAT_AGENT_INFO));
if (new_agent_info == NULL)
{
return(NAT_SYSTEM_ERROR);
}
agent_info->id = (u_long)new_agent_info; /* Use item pointer for ID */
memcpy(new_agent_info, agent_info, sizeof(NAT_AGENT_INFO));
semTake (agentListLock, WAIT_FOREVER);
lstAdd (&nat.agent_list, (NODE*) new_agent_info);
semGive (agentListLock);
return(NAT_OK);
}
/*****************************************************************************
Function: natUnregisterAgent
Description:
This function is called by the external agent to deregister itself from the
NAT service.
*****************************************************************************/
/******************************************************************************
*
* natUnregisterAgent - deregister an external agent for the NAT service
*
* The external agent calls this routine to deregister itself from NAT service.
*
* RETURNS
*
* \is
* \i NAT_OK
* Success.
* \i NAT_INVALID_NAT_ID
* Invalid NAT ID.
* \i NAT_INVALID_AGENT_ID
* Invalid agent ID.
* \i NAT_SYSTEM_ERROR
* Memory allocation error.
* \ie
*/
NAT_STATUS natUnregisterAgent
(
u_long nat_id, /* NAT service ID, from a natGetId() call. */
u_long agent_id /* Agent ID, from a natRegisterAgent() call. */
)
{
NAT_CLASS* nat_p;
NAT_AGENT_INFO* agent_info;
nat_p = (NAT_CLASS *) nat_id;
if (nat_p != &nat) /* for now, support only one instance */
{
return(NAT_INVALID_NAT_ID);
}
semTake (agentListLock, WAIT_FOREVER);
agent_info = (NAT_AGENT_INFO *) lstFirst(&nat.agent_list);
while (agent_info != NULL)
{
if (agent_info->id == agent_id)
{
lstDelete (&nat.agent_list, (NODE *) agent_info);
semGive (agentListLock);
free (agent_info);
return (NAT_OK);
}
agent_info = (NAT_AGENT_INFO *) lstNext((NODE *) agent_info);
}
semGive (agentListLock);
return (NAT_INVALID_AGENT_ID);
}
/*****************************************************************************
Function: natSetBind
Description:
This function is called by the external agent to create a new address bind or
set certain parameters of an existing bind. The bind can be an address bind
or transport bind. The caller is expected to fill in the NAT_BIND_INFO
structure. A new bind request is made by setting the bind ID (in NAT_BIND_INFO)
to 0. A non-zero bind ID would be interpreted to mean that the agent is
attempting to set some existing bind parameters.
If the caller requests for a bind creation, and NAT is successful in creating
a new bind, the function will fill the NAT_BIND_INFO structure with the newly
assigned bind ID. If the request is for setting some bind parameters and the
bind ID is valid, it will replace the NAT bind information with the new one.
NOTE:
Currently, only new bind creation is supported. For request to set existing
bind parameters, the input bind parameters will be copied to the existing bind
entry, but will have no effect on NAT.
*****************************************************************************/
/******************************************************************************
*
* natSetBind - create address bind or set parameters of existing bind
*
* The external agent calls this routine to create an address bind or to set
* parameters in an existing bind. The bind can be either an address bind or
* a transport bind. The caller is expected to fill in the NAT_BIND_INFO
* structure. A new bind request is made by setting the bind ID (in
* NAT_BIND_INFO) to 0. A non-zero bind ID is interpreted to mean that the
* agent is attempting to set some existing bind parameters.
*
* If the caller requests a bind creation, and NAT is successful in creating
* a bind, the routine fills the NAT_BIND_INFO structure with the
* newly assigned bind ID. If the request is for setting some bind parameters
* and the bind ID is valid, it replaces the existing bind's parameters with
* the new parameters.
*
* When creating a bind, NAT allocates its own bind descriptor and registers
* it in its bind-descriptor list. Therefore, it is important that the
* external agent fills in all of the requisite parameters in the
* bind-descriptor prior to passing it to NAT through this routine. NAT then
* copies these parameters to its own bind descriptor and creates the TCP or
* UDP control block for this bind based on the given parameters.
*
* 'Note:' Currently, only bind creation is supported. Setting the parameters
* in an existing bind is prohibited. When a non-zero bind ID is detected,
* this routine returns NAT_UNSUPPORTED_FEATURE (defined in natAlgApi.h). For
* the ALG, it is not clear what bind parameters may need modification.
* Incorrectly modified parameters could cause the unexpected disconnection
* of a session, as well as memory leaks. For this reason, WIND NET NAT ALG
* API does not support this feature until its purpose is better understood.
*
* RETURNS
* \is
* \i NAT_OK
* Success.
* \i NAT_INVALID_NAT_ID
* Invalid NAT ID.
* \i NAT_INVALID_AGENT_ID
* Invalid NAT agent ID.
* \i NAT_INVALID_ARG_PTR
* Invalid pointer to bind information.
* \i NAT_BIND_MAKE_FAILED
* Cannot create a bind.
* \i NAT_SYSTEM_ERROR
* Memory allocation error.
* \i NAT_UNSUPPORTED_FEATURE
* Unsupported feature.
* \ie
*
*/
NAT_STATUS natSetBind
(
u_long nat_id, /* NAT service ID, from a natGetID() call. */
u_long agent_id, /* Agent ID, from a netRegisterAgent() call. */
NAT_BIND_INFO* bind_info /* Pointer to bind information. */
)
{
NAT_CLASS* nat_p;
NAT_BIND_INFO* new_bind_info;
NAT_STATUS status;
BOOL static_flag;
u_short local_port_number, global_port_number, remote_port_number;
IP_ADDRESS local_address, global_address, remote_address;
NAT_CURRENCY_TRANSLATION_ENTRY *sptr_translation_entry=NULL;
IP_TRANSLATION_ENTRY *ip_translation_entry;
nat_p = (NAT_CLASS *) nat_id;
if (nat_p != &nat)
{
return(NAT_INVALID_NAT_ID);
}
if ((status = match_nat_agent(nat_id, agent_id)) != NAT_OK)
{
return(status);
}
if (bind_info == NULL)
{
return(NAT_INVALID_ARG_PTR);
}
semTake(bindListLock, WAIT_FOREVER);
static_flag = bind_info->static_entry;
local_address = (IP_ADDRESS) bind_info->local_addr;
local_port_number = bind_info->local_transport;
global_address = (IP_ADDRESS) bind_info->global_addr;
global_port_number = bind_info->global_transport;
remote_address = (IP_ADDRESS) bind_info->remote_addr;
remote_port_number = bind_info->remote_transport;
/* for a new bind request, must create an entry in the respective NAT translation
list, create a new bind entry and fill in the bind information.
*/
if (bind_info->id == 0) /* New bind request */
{
bind_info->agent_id = agent_id;
/* create a new bind in the NAT translation list */
if (bind_info->type == NAT_BIND_NAPT)
{
bind_info->id=0;
switch (bind_info->protocol)
{
case IPPROTO_TCP:
semTake(natentrylock, WAIT_FOREVER);
if ((sptr_translation_entry = (NAT_CURRENCY_TRANSLATION_ENTRY *) natTcpXlatAdd (
(u_long)local_address, local_port_number,
(u_long) remote_address, remote_port_number, static_flag)) == NULL)
{
/*free (new_bind_info);*/
semGive(natentrylock);
semGive (bindListLock);
return (NAT_BIND_MAKE_FAILED);
}
bind_info->global_addr = nat.global_address;
/* For outbound session, the global port is the spoofed port unless the
the option to use local port as the global port is set. However, for
inbound session, the global port is the same as the static TCP global
port (set by NAT).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -