📄 nath323alg.c
字号:
ip_addr = READ_ALIGN_SAFE32(data);
ip_addr = ntohl (ip_addr);
/* look for G's H245Address match */
if (ip_addr == bind_info.remote_addr)
{
port = READ_ALIGN_SAFE16(data + sizeof (IP_ADDRESS));
port = ntohs (port);
nat_printf(NAT_PRINTF_TRACE, "H225 ALG: H245Address from remote host found\n");
nat_printf(NAT_PRINTF_DATA,
"H225 ALG: Global host's H245Address is: ip = %x, port = %x\n",
ip_addr, port);
/* register H.245 ALG to NAT */
if (natRegisterAlg (nat_p, port, H245Alg, &h323Alg[H245Alg]) != OK)
{
nat_printf(NAT_PRINTF_ERROR,
"natH225Packet: Failed to register H245 ALG with remote H.245 port\n");
return (FALSE);
}
}
data++;
}
}
else /* session started by G */
{
/* search for L's transport address in the H225 payload.
If found, translate it to its real transport address.
*/
nat_printf(NAT_PRINTF_TRACE,
"H225 ALG: inbound packet, inbound session. Translate global transport to its local transport\n");
while ((data + IP_PORT_LENGTH) <= (data_start + data_length))
{
ip_addr = READ_ALIGN_SAFE32(data);
ip_addr = ntohl (ip_addr);
/* look for L's translated address match */
if (ip_addr == bind_info.global_addr)
{
port = READ_ALIGN_SAFE16(data + sizeof (IP_ADDRESS));
port = ntohs (port);
nat_printf(NAT_PRINTF_DATA,
"H225 ALG: global ip match found in H.225 payload, ip = %x, port = %x\n", ip_addr, port);
if (port == bind_info.global_transport)
{ /* replace with L's real transport address */
ip_data = (IP_ADDRESS *) data;
transport.ip_addr = htonl (bind_info.local_addr);
port_data = (USHORT *) (data + sizeof(IP_ADDRESS));
checksum = tcp_packet->tcp_header.checksum;
if (nat_p->type == NAT_TYPE_NAPT)
{
transport.port = htons (bind_info.local_transport);
natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_NAPT, &checksum);
}
else
{
transport.port = READ_ALIGN_SAFE16(port_data);
natAdjustChecksum((BYTE *)ip_data, &transport, NAT_BIND_BASIC, &checksum);
}
tcp_packet->tcp_header.checksum = checksum;
WRITE_ALIGN_SAFE32(ip_data, transport.ip_addr);
WRITE_ALIGN_SAFE16(port_data, transport.port);
data += IP_PORT_LENGTH;
nat_printf(NAT_PRINTF_DATA,
"H225 ALG: After translation, local ip = %x, port = %x\n",
ntohl(READ_ALIGN_SAFE32(ip_data)), ntohs(READ_ALIGN_SAFE16(port_data)));
}
else /* port != bind_info.global_transport */
{
data++;
}
}
else /* ip_addr != bind_info.global_addr */
{
data++;
}
} /* while */
} /* else (session started by G) */
} /* else (inbound packet) */
return (TRUE);
}
/**************************************************************************
Function: natH323Event
Description:
This callback function is called by NAT upon the H.245 termination.
The function frees the static UDP binds (RTP and RTCP logical channels)
as well as the T1.120 TCP bind created during the H.245 session.
**************************************************************************/
void natH245Event(u_long nat_id, u_long agent_id,
NAT_AGENT_EVENT event, NAT_EVENT_INFO *event_info)
{
NAT_STATUS status;
int i;
if (nat_instance[0].id != nat_id)
{
printf("natH245Event: Invalid nat id\n");
return;
}
if (agent_id != h323Alg[H245Alg].id)
{ /* return if event not generated from H.245 TCP packet */
nat_printf(NAT_PRINTF_ERROR, "natH245Event: not H245Alg\n"); /* tk */
return;
}
if (event != NAT_BIND_TERMINATION)
{
nat_printf(NAT_PRINTF_ERROR, "natH245Event: Call not for bind termination!\n");
return;
}
/* now delete all the UDP logical channels opened by H.245 */
for (i=0; i<MAX_LOGICAL_CHANNELS; i++)
{
if (logical_channel_bind[i] != 0)
{
status = natFreeBind (nat_id, agent_id, logical_channel_bind[i]);
if (status != NAT_OK)
{
nat_printf(NAT_PRINTF_ERROR,
"natH245Event: natFreeBind returned error status = %d, bind id = %x\n",
status, logical_channel_bind[i]);
}
else
{
logical_channel_bind[i] = 0;
}
}
}
}
/**************************************************************************
Function: natH323Init
Description:
This function is called when the H.323 ALG component is included in the
NAT components. It is called after the completion of NAT initialization.
This does the following:
- Query the NAT service
- Set up agent descriptor to describe the characteristics of the ALG
- Include the callback function natH323Packet to process the H.225 packets
- Register the ALG to NAT
The semaphore natInitSync is used to prevent the race condition between
the NAT initialization and the initializations of other agents when
included.
**************************************************************************/
STATUS natH323Init(u_short h323_port)
{
NAT_STATUS status;
int i;
semTake (natInitSync, WAIT_FOREVER); /* wait for event */
nat_printf(NAT_PRINTF_INIT, "H323 initialization: port = %u\n", h323_port);
memset(&nat_instance[0], 0, sizeof(NAT_ID_INFO));
status = natGetID(&nat_instance[0]); /* query the NAT service */
if (status != NAT_OK)
{
printf("natH323: natGetID failed with error %d\n", status);
semGive (natInitSync);
return(ERROR);
}
/* Register H225 ALG to NAT */
if (natRegisterAlg (&nat_instance[0], h323_port, H225Alg, &h323Alg[H225Alg]) != OK)
{
printf("natH323: Failed to register H225 ALG\n");
semGive (natInitSync);
return (ERROR);
}
printf("H323 ALG registered with NAT\n");
for (i=0; i<MAX_LOGICAL_CHANNELS; i++)
{
logical_channel_bind[i] = 0;
}
semGive (natInitSync);
return(OK);
}
STATUS natH323end(void)
{
semTake (natInitSync, WAIT_FOREVER); /* wait for event */
/* unregister H245 ALG to NAT */
if((natUnregisterAgent(nat_instance[0].id,h323Alg[H245Alg].id)) != OK)
{
printf("natH323: Failed to unregister H225 ALG\n");
semGive (natInitSync);
return (ERROR);
}
/* unregister H225 ALG to NAT */
if((natUnregisterAgent(nat_instance[0].id,h323Alg[H225Alg].id)) != OK)
{
printf("natH323: Failed to unregister H225 ALG\n");
semGive (natInitSync);
return (ERROR);
}
semGive (natInitSync);
return(OK);
}
/**************************************************************************
Function: natRegisterAlg
Description:
This function registers the given ALG type with NAT. In H.323 protocol,
we need to worry only the H.225 call signaling and H.245 call control ALGs.
**************************************************************************/
static STATUS natRegisterAlg (
NAT_ID_INFO *nat_id,
u_short port,
H323AlgType alg,
NAT_AGENT_INFO *agent_info_p)
{
NAT_STATUS status;
memset(agent_info_p, 0, sizeof(NAT_AGENT_INFO));
agent_info_p->type = NAT_AGENT_TYPE_ALG;
agent_info_p->flags = NAT_FLAG_POST_XLAT;
agent_info_p->session_tag.protocol = IPPROTO_TCP;
switch (alg)
{
case H225Alg:
agent_info_p->session_tag.transport = port;
agent_info_p->packet_callback = natH225Packet; /* packet callback */
sprintf(agent_info_p->desc, "%.*s",
(int)sizeof(agent_info_p->desc)-1, h225_alg_desc);
sprintf(agent_info_p->name, "%.*s",
(int)(sizeof(agent_info_p->name)-1), h225_alg_name);
break;
case H245Alg:
agent_info_p->session_tag.transport = port;
agent_info_p->packet_callback = natH245Packet; /* packet callback */
agent_info_p->event_callback = natH245Event; /* event callback */
sprintf(agent_info_p->desc, "%.*s",
(int)sizeof(agent_info_p->desc)-1, h245_alg_desc);
sprintf(agent_info_p->name, "%.*s",
(int)(sizeof(agent_info_p->name)-1), h245_alg_name);
break;
default:
printf("unknown H323 ALG\n");
return (ERROR);
}
status = natRegisterAgent(nat_id->id, agent_info_p); /* register the ALG */
if (status != NAT_OK)
{
return (ERROR);
}
return (OK);
}
/**************************************************************************
Function: natAdjustChecksum
Description:
This function adjusts the TCP checksum for changing the IP address and port
number. Different methods must be used depending on whether the data to
be replaced start at even or odd address.If at even address, do the checksum
adjustment normally. If at odd address, back-up to the nearest smaller
even address and do the checksum adjustment starting from there. This
extra step must be done because checksum is calculated by adding 2 bytes
at a time
**************************************************************************/
static void natAdjustChecksum(
BYTE *data,
TRANSPORT_ADDR *new_transport,
NAT_BIND_TYPE nat_type,
USHORT *checksum)
{
BYTE *old_byte_p, *new_byte_p;
BYTE old_data[IP_PORT_LENGTH], new_data[IP_PORT_LENGTH];
int i;
if (((ULONG)data) % 2) /* odd address */
{
/* go to the nearest lower even address and adjust checksum for 6 bytes,
note this includes:
1 byte before IP address + IP address (4 bytes) + first byte of port
*/
old_byte_p = (BYTE *) data;
old_byte_p--;
new_data[0] = *old_byte_p; /* byte before IP */
for (i=0; i<IP_PORT_LENGTH; i++)
{
old_data[i] = *old_byte_p++;
}
new_byte_p = (BYTE *) &new_transport->ip_addr;
for (i=1; i<(IP_PORT_LENGTH-1); i++)
{
new_data[i] = *new_byte_p++;
}
new_byte_p = (BYTE *) &new_transport->port;
new_data[i] = *new_byte_p++;
checksum_fixup ((BYTE *) checksum,
old_data, IP_PORT_LENGTH,
new_data, IP_PORT_LENGTH);
/* for NAPT, we still need to account for the change in the last
byte of the port number. Adjust checksum for 2 bytes:
1 byte of 2nd byte of port + 1 byte after port
*/
if (nat_type == NAT_BIND_NAPT)
{
old_data[0] = *old_byte_p++; /* old port */
old_data[1] = *old_byte_p;
new_data[0] = *new_byte_p; /* translated port */
new_data[1] = *old_byte_p;
checksum_fixup ((BYTE *) checksum,
old_data, (USHORT) 2,
new_data, (USHORT) 2);
}
}
else /* even address */
{
checksum_fixup ((BYTE *) checksum,
(BYTE *) data, sizeof(IP_ADDRESS),
(BYTE *) &new_transport->ip_addr, sizeof(IP_ADDRESS));
if (nat_type == NAT_BIND_NAPT)
{
checksum_fixup ((BYTE *) checksum,
(BYTE *) (data + sizeof(IP_ADDRESS)), sizeof(USHORT),
(BYTE *) &new_transport->port, sizeof(USHORT));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -