vpp/plugins/vcgn-plugin/vcgn/cnat_syslog.c
Ole Troan ea3e1fc875 Plugins: Clean up the plugin directory so that each plugin has its own
directory and GNU autotools setup.

Change-Id: I6c59d1297389c9413db0c0b9bdf3b759080bf1b8
Signed-off-by: Ole Troan <ot@cisco.com>
2016-06-27 15:04:00 +00:00

1788 lines
56 KiB
C

/*
*------------------------------------------------------------------
* cnat_syslog.c
*
* Copyright (c) 2011-2013 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*------------------------------------------------------------------
*/
#include <arpa/inet.h>
#include "cnat_syslog.h"
#include "platform_common.h"
#include "cnat_db.h"
#include "cnat_log_common.h"
#include <vppinfra/pool.h>
#define SYSLOG_DELIMITER ' '
#define SYSLOG_FIELD_ABSENT '-'
/* #define SHOW_SYSLOG_TIMESTAMP 1 TO DO. Remove this later */
/*
* Defining the below macro here for now. Assumption is, syslog packets
* are sent out via same channel as that of NFV9.
* Has to be overridden if this assumption is false.
*/
#define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX
cnat_syslog_global_info_t cnat_syslog_global_info;
cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool;
cnat_syslog_global_counters_t cnat_syslog_global_counter;
extern u32 syslog_debug_flag;
#define CNAT_SYSLOG_DEBUG_CODE 2
#if CNAT_SYSLOG_DEBUG_CODE > 3
#define SYSLOG_COND if(my_instance_number == 0)
#define SYSLOG_DEBUG_PRINTF1(a) SYSLOG_COND printf(a);
#define SYSLOG_DEBUG_PRINTF2(a, b) SYSLOG_COND printf(a, b);
#define SYSLOG_DEBUG_PRINTF3(a, b, c) SYSLOG_COND printf(a, b, c);
#define SYSLOG_DEBUG_PRINTF4(a, b, c, d) SYSLOG_COND printf(a, b, c, d);
#else
#define SYSLOG_DEBUG_PRINTF1(a)
#define SYSLOG_DEBUG_PRINTF2(a, b)
#define SYSLOG_DEBUG_PRINTF3(a, b, c)
#define SYSLOG_DEBUG_PRINTF4(a, b, c, d)
#endif
void syslog_params_show(u32 logging_index)
{
cnat_syslog_logging_info_t *log_info __attribute__((unused));
if(logging_index == EMPTY) {
PLATFORM_DEBUG_PRINT("\nSyslog logging not configured\n");
return;
}
log_info = cnat_syslog_logging_info_pool + logging_index;
PLATFORM_DEBUG_PRINT("\nSyslog parameters --\n");
PLATFORM_DEBUG_PRINT("IPV4 address: %x, port %d, max log size %d\n",
log_info->ipv4_address,
log_info->port, log_info->max_length_minus_max_record_size);
PLATFORM_DEBUG_PRINT("Host name: %s, priority %d",
log_info->header_hostname, log_info->header_priority);
}
/* Util function to copy a number as ASCII in to a buf in a
* faster way (should be faster than sprintf)
*/
const unsigned char ascii_numbers[][3] =
{ {'0', '0', '0'},
{'1', '0', '0'},
{'2', '0', '0'},
{'3', '0', '0'},
{'4', '0', '0'},
{'5', '0', '0'},
{'6', '0', '0'},
{'7', '0', '0'},
{'8', '0', '0'},
{'9', '0', '0'},
{'1', '0', '0'},
{'1', '1', '0'},
{'1', '2', '0'},
{'1', '3', '0'},
{'1', '4', '0'},
{'1', '5', '0'},
{'1', '6', '0'},
{'1', '7', '0'},
{'1', '8', '0'},
{'1', '9', '0'},
{'2', '0', '0'},
{'2', '1', '0'},
{'2', '2', '0'},
{'2', '3', '0'},
{'2', '4', '0'},
{'2', '5', '0'},
{'2', '6', '0'},
{'2', '7', '0'},
{'2', '8', '0'},
{'2', '9', '0'},
{'3', '0', '0'},
{'3', '1', '0'},
{'3', '2', '0'},
{'3', '3', '0'},
{'3', '4', '0'},
{'3', '5', '0'},
{'3', '6', '0'},
{'3', '7', '0'},
{'3', '8', '0'},
{'3', '9', '0'},
{'4', '0', '0'},
{'4', '1', '0'},
{'4', '2', '0'},
{'4', '3', '0'},
{'4', '4', '0'},
{'4', '5', '0'},
{'4', '6', '0'},
{'4', '7', '0'},
{'4', '8', '0'},
{'4', '9', '0'},
{'5', '0', '0'},
{'5', '1', '0'},
{'5', '2', '0'},
{'5', '3', '0'},
{'5', '4', '0'},
{'5', '5', '0'},
{'5', '6', '0'},
{'5', '7', '0'},
{'5', '8', '0'},
{'5', '9', '0'},
{'6', '0', '0'},
{'6', '1', '0'},
{'6', '2', '0'},
{'6', '3', '0'},
{'6', '4', '0'},
{'6', '5', '0'},
{'6', '6', '0'},
{'6', '7', '0'},
{'6', '8', '0'},
{'6', '9', '0'},
{'7', '0', '0'},
{'7', '1', '0'},
{'7', '2', '0'},
{'7', '3', '0'},
{'7', '4', '0'},
{'7', '5', '0'},
{'7', '6', '0'},
{'7', '7', '0'},
{'7', '8', '0'},
{'7', '9', '0'},
{'8', '0', '0'},
{'8', '1', '0'},
{'8', '2', '0'},
{'8', '3', '0'},
{'8', '4', '0'},
{'8', '5', '0'},
{'8', '6', '0'},
{'8', '7', '0'},
{'8', '8', '0'},
{'8', '9', '0'},
{'9', '0', '0'},
{'9', '1', '0'},
{'9', '2', '0'},
{'9', '3', '0'},
{'9', '4', '0'},
{'9', '5', '0'},
{'9', '6', '0'},
{'9', '7', '0'},
{'9', '8', '0'},
{'9', '9', '0'},
{'1', '0', '0'},
{'1', '0', '1'},
{'1', '0', '2'},
{'1', '0', '3'},
{'1', '0', '4'},
{'1', '0', '5'},
{'1', '0', '6'},
{'1', '0', '7'},
{'1', '0', '8'},
{'1', '0', '9'},
{'1', '1', '0'},
{'1', '1', '1'},
{'1', '1', '2'},
{'1', '1', '3'},
{'1', '1', '4'},
{'1', '1', '5'},
{'1', '1', '6'},
{'1', '1', '7'},
{'1', '1', '8'},
{'1', '1', '9'},
{'1', '2', '0'},
{'1', '2', '1'},
{'1', '2', '2'},
{'1', '2', '3'},
{'1', '2', '4'},
{'1', '2', '5'},
{'1', '2', '6'},
{'1', '2', '7'},
{'1', '2', '8'},
{'1', '2', '9'},
{'1', '3', '0'},
{'1', '3', '1'},
{'1', '3', '2'},
{'1', '3', '3'},
{'1', '3', '4'},
{'1', '3', '5'},
{'1', '3', '6'},
{'1', '3', '7'},
{'1', '3', '8'},
{'1', '3', '9'},
{'1', '4', '0'},
{'1', '4', '1'},
{'1', '4', '2'},
{'1', '4', '3'},
{'1', '4', '4'},
{'1', '4', '5'},
{'1', '4', '6'},
{'1', '4', '7'},
{'1', '4', '8'},
{'1', '4', '9'},
{'1', '5', '0'},
{'1', '5', '1'},
{'1', '5', '2'},
{'1', '5', '3'},
{'1', '5', '4'},
{'1', '5', '5'},
{'1', '5', '6'},
{'1', '5', '7'},
{'1', '5', '8'},
{'1', '5', '9'},
{'1', '6', '0'},
{'1', '6', '1'},
{'1', '6', '2'},
{'1', '6', '3'},
{'1', '6', '4'},
{'1', '6', '5'},
{'1', '6', '6'},
{'1', '6', '7'},
{'1', '6', '8'},
{'1', '6', '9'},
{'1', '7', '0'},
{'1', '7', '1'},
{'1', '7', '2'},
{'1', '7', '3'},
{'1', '7', '4'},
{'1', '7', '5'},
{'1', '7', '6'},
{'1', '7', '7'},
{'1', '7', '8'},
{'1', '7', '9'},
{'1', '8', '0'},
{'1', '8', '1'},
{'1', '8', '2'},
{'1', '8', '3'},
{'1', '8', '4'},
{'1', '8', '5'},
{'1', '8', '6'},
{'1', '8', '7'},
{'1', '8', '8'},
{'1', '8', '9'},
{'1', '9', '0'},
{'1', '9', '1'},
{'1', '9', '2'},
{'1', '9', '3'},
{'1', '9', '4'},
{'1', '9', '5'},
{'1', '9', '6'},
{'1', '9', '7'},
{'1', '9', '8'},
{'1', '9', '9'},
{'2', '0', '0'},
{'2', '0', '1'},
{'2', '0', '2'},
{'2', '0', '3'},
{'2', '0', '4'},
{'2', '0', '5'},
{'2', '0', '6'},
{'2', '0', '7'},
{'2', '0', '8'},
{'2', '0', '9'},
{'2', '1', '0'},
{'2', '1', '1'},
{'2', '1', '2'},
{'2', '1', '3'},
{'2', '1', '4'},
{'2', '1', '5'},
{'2', '1', '6'},
{'2', '1', '7'},
{'2', '1', '8'},
{'2', '1', '9'},
{'2', '2', '0'},
{'2', '2', '1'},
{'2', '2', '2'},
{'2', '2', '3'},
{'2', '2', '4'},
{'2', '2', '5'},
{'2', '2', '6'},
{'2', '2', '7'},
{'2', '2', '8'},
{'2', '2', '9'},
{'2', '3', '0'},
{'2', '3', '1'},
{'2', '3', '2'},
{'2', '3', '3'},
{'2', '3', '4'},
{'2', '3', '5'},
{'2', '3', '6'},
{'2', '3', '7'},
{'2', '3', '8'},
{'2', '3', '9'},
{'2', '4', '0'},
{'2', '4', '1'},
{'2', '4', '2'},
{'2', '4', '3'},
{'2', '4', '4'},
{'2', '4', '5'},
{'2', '4', '6'},
{'2', '4', '7'},
{'2', '4', '8'},
{'2', '4', '9'},
{'2', '5', '0'},
{'2', '5', '1'},
{'2', '5', '2'},
{'2', '5', '3'},
{'2', '5', '4'},
{'2', '5', '5'}
};
inline static int
byte_to_ascii_decimal_unaligned(
unsigned char *ptr, unsigned char num)
{
*ptr++ = ascii_numbers[num][0];
if(PREDICT_FALSE(num < 10)) {
return 1;
}
*ptr++ = ascii_numbers[num][1];
if(PREDICT_FALSE(num < 100)) {
return 2;
}
*ptr++ = ascii_numbers[num][2];
return 3;
}
/* Copies the dotted decimal format of ipv4
* in to the space provided and
* returns the number of bytes copied
*/
inline static int __attribute__((unused))
copy_ipv4_addr(unsigned char *ptr, u32 ipv4)
{
unsigned char *temp = ptr;
temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 >> 24));
*temp++ = '.';
temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 16) & 0xFF));
*temp++ = '.';
temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 8) & 0xFF));
*temp++ = '.';
temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 & 0xFF));
return (temp - ptr);
}
#ifdef TOBE_PORTED
/*
* edt: * * cnat_syslog_fill_ip_header
*
* Tries to fill the fields of the IP header before it
* is sent to the L3 infra node.
*
* Argument: cnat_syslog_logging_info_t *logging_info
* structure that contains the packet context
*/
inline
void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info)
{
spp_ctx_t *ctx;
/*
* Fill in the IP header and port number of the Netflow collector
* The L3 Infra node will fill in the rest of the fields
*/
ctx = logging_info->current_logging_context;
fill_ip_n_udp_hdr(ctx, logging_info->ipv4_address,
logging_info->port, logging_info->pkt_length);
}
#else
inline
void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info)
{
return;
}
#endif
#ifndef TOBE_PORTED
void cnat_syslog_logging_init()
{
return;
}
void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db,
cnat_vrfmap_t *vrfmap)
{
return;
}
void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db,
cnat_vrfmap_t *vrfmap)
{
return;
}
void cnat_syslog_ds_lite_port_limit_exceeded(
dslite_key_t * key,
dslite_table_entry_t *dslite_entry)
{
return;
}
void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db,
cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb
#ifndef NO_BULK_LOGGING
, int bulk_alloc
#endif
)
{
return;
}
/* Following are in cnat_util.c which are not ported */
/* This function is defined in cnat_util.c which need to be ported */
cnat_icmp_msg_t icmp_msg_gen_allowed ()
{
return 1;
}
void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db,
cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb
#ifndef NO_BULK_LOGGING
, int bulk_alloc
#endif
)
{
return;
}
u32
cnat_get_unix_time_in_seconds (void)
{
return 0;
}
#else /* TOBE_PORTED */
void
cnat_syslog_dump_logging_context (u32 value1,
cnat_syslog_logging_info_t *logging_info,
u32 value2)
{
u8 *pkt_ptr;
u32 i;
if (PREDICT_TRUE(syslog_debug_flag == 0)) {
return;
}
/*
* Reduce the logging to few cores, to enable easier debugging
*/
if ((my_instance_number & 0x7) != 0) {
return;
}
printf("\nDumping %s packet at locn %d: time 0x%x",
(value2 == 1) ? "CURRENT" : "QUEUED",
value1,
cnat_get_unix_time_in_seconds());
printf("\ni_vrf 0x%x, ip_address 0x%x, port %d, pkt len %d",
0 /* TO DP Add vrf like nfv9_logging_info->i_vrf */,
logging_info->ipv4_address,
logging_info->port,
logging_info->pkt_length);
printf("\n");
if (value2 == 1) {
pkt_ptr = logging_info->current_logging_context->packet_data;
} else {
pkt_ptr = logging_info->queued_logging_context->packet_data;
}
/*
* Dump along with 8 bytes of SHIM header
*/
for (i = 0; i <
(logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET);
i = i + 1) {
u8 c1, c2, c3;
if (i == 0) {
printf("\nL2_HEADER + SHIM_HEADER: \n");
} else if (i == CNAT_NFV9_IP_HDR_OFFSET) {
printf("\nIP_HEADER: \n");
} else if (i == CNAT_NFV9_UDP_HDR_OFFSET) {
printf("\nUDP_HEADER: \n");
} else if (i == CNAT_NFV9_HDR_OFFSET) {
printf("\nSyslog content..\n");
while(i <
(logging_info->pkt_length + CNAT_NFV9_HDR_OFFSET)) {
printf("%c", (u8)(*(pkt_ptr + i)));
i++;
if((u8)(*(pkt_ptr + i)) == '[') /* new record begins */
printf("\n");
}
return;
}
c3 = *(pkt_ptr + i);
c2 = c3 & 0xf;
c1 = (c3 >> 4) & 0xf;
printf("%c%c ",
((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')),
((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a')));
}
printf("\n");
}
/*
* edt: * * cnat_syslog_send_pkt
*
* Tries to send a logging pkt. If the packet cannot be sent
* because of rewrite_output node cannot process it, queue
* it temporarily and try to send it later.
*
* Argument: cnat_syslog_logging_info_t *logging_info
* structure that contains the packet context
*/
inline
void cnat_syslog_send_pkt (cnat_syslog_logging_info_t *logging_info)
{
spp_node_t *output_node;
cnat_syslog_fill_ip_header(logging_info);
output_node = spp_get_nodes() +
cnat_syslog_global_info.cnat_syslog_disp_node_index;
cnat_syslog_dump_logging_context (2, logging_info, 1);
if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
/*
* Move the logging context to output node
*/
logging_info->current_logging_context->current_length =
logging_info->pkt_length;
PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->current_logging_context, \
NODE_LOGGING);
spp_dispatch_make_node_runnable(output_node);
output_node->sf.ctxs[output_node->sf.nused++] =
logging_info->current_logging_context;
if(PREDICT_FALSE(syslog_debug_flag > 10))
printf("\nSyslog: 2. Sending Current packet\n");
} else {
/*
* Queue the context into the logging_info structure,
* We will try to send it later. Currently, we will
* restrict to only one context queued.
*/
cnat_syslog_global_counter.downstream_constipation_count++;
if(PREDICT_FALSE(syslog_debug_flag > 10))
printf("\nSyslog: 2. Downstream congestion \n");
/*
* Attach the current logging context which is full to the
* queued context list in logging_info structure
*/
logging_info->queued_logging_context =
logging_info->current_logging_context;
}
/*
* Whether the context is queued or not, set the current context index
* to EMPTY, as the earlier context can no more be used to send
* more logging records.
*/
logging_info->current_logging_context = NULL;
}
/*
* edt: * * cnat_syslog_send_queued_pkt
*
* Tries to send a logging pkt that has been queued earlier
* because it could not be sent due to downstream constipation
*
* Argument: cnat_syslog_logging_info_t *logging_info
* structure that contains the packet context
*/
inline
void cnat_syslog_send_queued_pkt (cnat_syslog_logging_info_t *logging_info)
{
spp_node_t *output_node;
output_node = spp_get_nodes() +
cnat_syslog_global_info.cnat_syslog_disp_node_index;
cnat_syslog_dump_logging_context(1, logging_info, 2);
if(PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) {
/*
* Move the logging context to output node
*/
/** This looks like a bug to me .. need to confirm *****
logging_info->queued_logging_context->current_length =
nfv9_logging_info->pkt_length; ***/
PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->queued_logging_context,
NODE_LOGGING)
spp_dispatch_make_node_runnable(output_node);
output_node->sf.ctxs[output_node->sf.nused++] =
logging_info->queued_logging_context;
SYSLOG_DEBUG_PRINTF1("\nSYSLOG: 1. Sending Queued packet\n")
/*
* Context has been queued, it will be freed after the pkt
* is sent. Clear this from the logging_context_info structure
*/
logging_info->queued_logging_context = NULL;
} else {
cnat_syslog_global_counter.downstream_constipation_count++;
}
}
/*
* edt: * * handle_pending_syslog_pkts
*
* Timer handler for sending any pending syslog record
*
*/
inline
void handle_pending_syslog_pkts()
{
spp_node_t *output_node;
cnat_syslog_logging_info_t *my_logging_info = 0;
u32 current_timestamp = cnat_get_sys_up_time_in_ms();
i16 sf_nused;
output_node = spp_get_nodes() +
cnat_syslog_global_info.cnat_syslog_disp_node_index;
sf_nused = output_node->sf.nused;
pool_foreach (my_logging_info, cnat_syslog_logging_info_pool, ({
/*
* Check if no more logging contexts can be queued
*/
if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) {
break;
}
if (my_logging_info->queued_logging_context)
cnat_syslog_send_queued_pkt (my_logging_info);
if(my_logging_info->current_logging_context &&
((current_timestamp -
my_logging_info->current_logging_context_timestamp)
> 1000)) {
/*
* If there is a current logging context and timestamp
* indicates it is pending for long, send it out
* Also if there is a queued context send it out as well
*/
SYSLOG_DEBUG_PRINTF4("\nLOG_TIMER: queued %p, curr %p, sf_nused %d",
my_logging_info->queued_logging_context,
my_logging_info->current_logging_context,
sf_nused);
cnat_syslog_send_pkt(my_logging_info);
}
}));
}
const unsigned char hex_numbers_single_digit[] =
{ '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
inline static int u16_to_ascii_decimal_aligned(
unsigned char *ptr, u16 num, u16 min_digits)
{
/* The logic below is replicated in
* function u16_to_ascii_decimal_unaligned
* except the use of min_digits
* Replication is done to optimize run time
* if you fix a bug here, check u16_to_ascii_decimal_unaligned
* as well (and vice versa)
*/
unsigned char *temp = ptr;
int no_leading_zeros = 0;
if(num > 9999 || min_digits == 5) {
*temp++ = hex_numbers_single_digit[num/10000];
num = num%10000;
no_leading_zeros = 1;
}
if(no_leading_zeros || num > 999 || min_digits == 4) {
*temp++ = hex_numbers_single_digit[num/1000];
num = num%1000;
no_leading_zeros = 1;
}
if(no_leading_zeros || num > 99 || min_digits == 3) {
*temp++ = hex_numbers_single_digit[num/100];
num = num%100;
no_leading_zeros = 1;
}
if(no_leading_zeros || num > 9 || min_digits == 2) {
*temp++ = hex_numbers_single_digit[num/10];
num = num%10;
}
*temp++ = hex_numbers_single_digit[num];
return temp-ptr;
}
inline static int u16_to_ascii_decimal_unaligned(
unsigned char *ptr, u16 num)
{
/*
* return u16_to_ascii_decimal_aligned(ptr, num, 0);
* should do the job.. however, to opimize the run time
* the code of u16_to_ascii_decimal_aligned is being
* repeated here without the use of min_digits
* if you fix a bug here, please check
* u16_to_ascii_decimal_aligned as well (and vice versa)
*/
unsigned char *temp = ptr;
int no_leading_zeros = 0;
if(num > 9999) {
*temp++ = hex_numbers_single_digit[num/10000];
num = num%10000;
no_leading_zeros = 1;
}
if(no_leading_zeros || num > 999) {
*temp++ = hex_numbers_single_digit[num/1000];
num = num%1000;
no_leading_zeros = 1;
}
if(no_leading_zeros || num > 99) {
*temp++ = hex_numbers_single_digit[num/100];
num = num%100;
no_leading_zeros = 1;
}
if(no_leading_zeros || num > 9) {
*temp++ = hex_numbers_single_digit[num/10];
num = num%10;
}
*temp++ = hex_numbers_single_digit[num];
return temp-ptr;
}
static int syslog_get_timestamp(unsigned char *ts)
{
static const char *months[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ",
"Jun ", "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec " };
unsigned char *temp = ts;
/* Inserts time stamp in the syslog format and returns lenght
* assumes that ts has sufficient space
*/
/* China Telecom has demanded that the time stamp has to be
* in the format '2011 Jun 7 12:34:08'
*/
time_t time = (time_t)cnat_get_unix_time_in_seconds();
struct tm tm1;
gmtime_r(&time, &tm1);
/* Now put the pieces together */
/* Year */
ts += u16_to_ascii_decimal_unaligned(ts, (tm1.tm_year + 1900));
*ts++ = SYSLOG_DELIMITER;
/* Month */
clib_memcpy(ts, months[tm1.tm_mon], 4);
ts += 4; /* DELIMITER taken care */
/* day */
ts += u16_to_ascii_decimal_unaligned(ts, tm1.tm_mday);
*ts++ = SYSLOG_DELIMITER;
/* hours */
ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_hour, 2);
*ts++ = ':';
/* minutes */
ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_min, 2);
*ts++ = ':';
/* seconds */
ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_sec, 2);
return ts - temp;
}
/* Ensure that the order of the below array matches with
* syslog_service_type enum
*/
static char *syslog_service_string[] = { "NAT44", "DSLITE" };
/* Ensure that the order of below array matches with
* syslog_event_type_t enum
*/
typedef struct {
char *event_name;
int name_length;
} syslog_event_description_type;
const static syslog_event_description_type sys_log_event[] = {
{ "UserbasedA", 10 }, /* yes, 10 is strlen of "UserbasedA" */
{ "UserbasedW", 10 },
{ "SessionbasedA", 13 },
{ "SessionbasedW", 13 },
{ "SessionbasedAD", 14 },
{ "SessionbasedWD", 14 },
{ "Portblockrunout", 15 },
{ "TCPseqmismatch", 14},
{ "Invalid", 7 }
};
inline static int syslog_fill_header(const cnat_syslog_logging_info_t *log_info,
syslog_service_type_t s_type)
{
/* Forms the syslog header and returns the lenght
* Assumes that header has sufficient space
*/
/* Sample header (as agreed for China Telecom requirements --
* <134> 1 2011 May 31 10:30:45 192.168.2.3 - - NAT44 -
*/
unsigned char *temp, *header;
int count;
temp = header = (unsigned char *)
&(log_info->current_logging_context->packet_data[CNAT_NFV9_HDR_OFFSET]);
*temp++ = '<';
temp += byte_to_ascii_decimal_unaligned(temp,
log_info->header_priority);
*temp++ = '>';
*temp++ = SYSLOG_DELIMITER;
*temp++ = '1'; /* Syslog version -- always set to 1 */
*temp++ = SYSLOG_DELIMITER;
temp += syslog_get_timestamp(temp);
*temp++ = SYSLOG_DELIMITER;
count = strlen(log_info->header_hostname);
clib_memcpy(temp, log_info->header_hostname, count);
temp += count;
*temp++ = SYSLOG_DELIMITER;
*temp++ = SYSLOG_FIELD_ABSENT; /* App name - nil value */
*temp++ = SYSLOG_DELIMITER;
*temp++ = SYSLOG_FIELD_ABSENT; /* Proc ID - nil value for now */
*temp++ = SYSLOG_DELIMITER;
/* Now the msg id */
count = strlen(syslog_service_string[s_type]);
clib_memcpy(temp, syslog_service_string[s_type], count);
temp += count;
*temp++ = SYSLOG_DELIMITER;
*temp++ = SYSLOG_FIELD_ABSENT; /* No structured elements */
*temp++ = SYSLOG_DELIMITER;
#ifdef SHOW_SYSLOG_TIMESTAMP
printf("\nSysLog TS: %s : Length %d", header, temp - header);
#endif /* SHOW_SYSLOG_TIMESTAMP */
return temp-header;
}
extern void cnat_logging_init();
/* one time call at the beginning */
void cnat_syslog_logging_init()
{
if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done))
return; /* Already done */
cnat_logging_init();
cnat_syslog_global_info.cnat_syslog_disp_node_index =
spp_lookup_node_index(PLATFORM_SYSLOG_DISP_NODE_IDX);
ASSERT(cnat_syslog_global_info.cnat_syslog_disp_node_index != (u16)~0);
cnat_syslog_global_info.cnat_syslog_init_done = 1;
}
/*
* edt: * * cnat_syslog_create_logging_context
*
* Tries to create a logging context with packet buffer
* to send a new logging packet
*
* Argument: cnat_syslog_logging_info_t *logging_info
* structure that contains the logging info and will store
* the packet context as well.
*/
inline
void cnat_syslog_create_logging_context (
cnat_syslog_logging_info_t *logging_info,
syslog_service_type_t s_type)
{
spp_ctx_t *ctx;
/*
* If queued_logging_context_index is non-EMPTY, we already have a logging
* packet queued to be sent. First try sending this before allocating
* a new context. We can have only one active packet context per
* logging_info structure
*/
if (PREDICT_FALSE(logging_info->queued_logging_context != NULL)) {
cnat_syslog_send_queued_pkt(logging_info);
/*
* If we cannot still send the queued pkt, just return
* Downstream Constipation count would have increased anyway
*/
if (logging_info->queued_logging_context != NULL) {
cnat_syslog_global_counter.logging_context_creation_deferred_count++;
return;
}
}
/*
* If no context can be allocated, return silently
* calling routine will handle updating the error counters
*/
if (spp_ctx_alloc(&ctx, 1) < 1) {
cnat_syslog_global_counter.logging_context_creation_fail_count++;
SYSLOG_DEBUG_PRINTF1("\nCould not allocate ctx for syslog");
return;
}
// Allocate packet buffer (used for AVSM currently)
PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, 0);
logging_info->current_logging_context = ctx;
PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, NODE_LOGGING);
ctx->flags = SPP_CTX_END_OF_PACKET;
ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX;
ctx->current_header = &ctx->packet_data[CNAT_NFV9_HDR_OFFSET];
logging_info->pkt_length = syslog_fill_header(logging_info, s_type);
logging_info->pkt_length += (CNAT_NFV9_HDR_OFFSET -
CNAT_NFV9_IP_HDR_OFFSET);
logging_info->current_logging_context_timestamp =
cnat_get_sys_up_time_in_ms();
}
inline static int u16_to_ascii_hex_unaligned(
unsigned char *ptr, u16 num)
{
unsigned char nibble, *temp;
int no_leading_zeros = 0;
temp = ptr;
nibble = (num >> 12);
if(nibble) {
*temp++ = hex_numbers_single_digit[nibble];
no_leading_zeros = 1;
}
nibble = (num >> 8) & 0xF;
if(nibble || no_leading_zeros) {
*temp++ = hex_numbers_single_digit[nibble];
no_leading_zeros = 1;
}
nibble = (num >> 4) & 0xF;
if(nibble || no_leading_zeros) {
*temp++ = hex_numbers_single_digit[nibble];
}
*temp++ = hex_numbers_single_digit[num & 0xF];
return temp-ptr;
}
inline static int ipv6_int_2_str(u32 ipv6[], unsigned char *ipv6_str)
{
/* DC stands for Double Colon.
* Refer http://tools.ietf.org/html/rfc5952 for
* more details on text representations of
* IPV6 address
*/
#define DC_NOT_USED_YET 0
#define DC_IN_USE 1 /* Zeros are skipped */
#define DC_ALREADY_USED 2 /* Cannot skip zeros anymore */
int i;
u16 *ipv6_temp = (u16 *)ipv6;
unsigned char *temp = ipv6_str;
int double_colon = DC_NOT_USED_YET;
for(i = 0; i < 7; i++) {
if(ipv6_temp[i]) {
ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[i]);
*ipv6_str++ = ':';
if(double_colon == DC_IN_USE) { /* Cannot use DC anymore */
double_colon = DC_ALREADY_USED;
}
} else {
if(double_colon == DC_IN_USE) {
/* Skip this zero as well */
continue;
} else if((ipv6_temp[i+1])
/* DC makes sense if there is more than one contiguous zero */
|| (double_colon != DC_NOT_USED_YET)) {
ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str,
ipv6_temp[i]);
*ipv6_str++ = ':';
} else { /* Start using DC */
*ipv6_str++ = ':'; /* The 2nd colon */
double_colon = DC_IN_USE;
}
}
}
if(ipv6_temp[7]) {
ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[7]);
} else if(double_colon != DC_IN_USE) {
*ipv6_str++ = '0';
}
*ipv6_str = 0;
return ipv6_str - temp;
}
/* insert syslog record for nat44 */
void cnat_syslog_insert_nat44_record(
cnat_syslog_logging_info_t *log_info,
cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap,
cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type)
{
/* This record should like this -
* [EventName <L4> <Original Source IP> <Inside VRF Name>
* <Original Source IPv6> < Translated Source IP> <Original Port>
* <Translated First Source Port> <Translated Last Source Port>
* <Destination ip address> <destination port>]
*/
u32 original_source = db->in2out_key.k.ipv4;
u32 translated_ip = db->out2in_key.k.ipv4;
cnat_user_db_entry_t *udb = cnat_user_db + db->user_index;
unsigned char *temp, *record;
u32 network_order_ipv6[4];
SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
temp = record = &(log_info->current_logging_context->packet_data[
CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
if (PREDICT_FALSE(!udb)) {
SYSLOG_DEBUG_PRINTF1("\nnull udb!");
return;
}
/* Now we point to the location where record needs to be inserted */
*record++ = '['; /* Open the record */
/* Copy the record type */
clib_memcpy(record, sys_log_event[e_type].event_name,
sys_log_event[e_type].name_length);
record += sys_log_event[e_type].name_length;
*record++ = SYSLOG_DELIMITER;
/* Copy the Protocol type */
if(PREDICT_FALSE(
e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
u16 my_proto_mask;
my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK;
if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
*record++ = '6';
} else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
*record++ = '1';
*record++ = '7';
} else if(PREDICT_TRUE(my_proto_mask == CNAT_ICMP)) {
*record++ = '1';
} else { /* Default, assume GRE (for PPTP) */
*record++ = '4';
*record++ = '7';
}
} else {
*record++ = SYSLOG_FIELD_ABSENT;
}
*record++ = SYSLOG_DELIMITER;
/* Copy the Original Source IP */
record += copy_ipv4_addr(record, original_source);
*record++ = SYSLOG_DELIMITER;
/* copy configured VRF NAME */
clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
record += log_info->vrf_name_len;
*record++ = SYSLOG_DELIMITER;
/* No IPV6 source address for nat44 */
*record++ = SYSLOG_FIELD_ABSENT;
*record++ = SYSLOG_DELIMITER;
/* Copy the translated IP address */
record += copy_ipv4_addr(record, translated_ip);
*record++ = SYSLOG_DELIMITER;
/* Copy the Original port */
if(e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) {
record += u16_to_ascii_decimal_unaligned(
record, db->in2out_key.k.port);
} else {
*record++ = SYSLOG_FIELD_ABSENT;
}
*record++ = SYSLOG_DELIMITER;
/* Copy the start outside port */
record += u16_to_ascii_decimal_unaligned(record, bulk_alloc);
*record++ = SYSLOG_DELIMITER;
/* Copy the last outside port */
if(e_type == userbased_assign || e_type == userbased_withdraw) {
record += u16_to_ascii_decimal_unaligned(record,
(bulk_alloc + BULKSIZE_FROM_VRFMAP(vrfmap) - 1));
} else {
*record++ = SYSLOG_FIELD_ABSENT;
}
*record++ = SYSLOG_DELIMITER;
/* Copy destination ip and port in case for DBL*/
if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
if(PREDICT_TRUE(sdb == NULL)) {
record += copy_ipv4_addr(record,db->dst_ipv4);
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(record, db->dst_port);
} else {
record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4);
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port);
}
} else {
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = '-';
}
*record++ = SYSLOG_DELIMITER;
*record++ = ']'; /* End of the reocrd */
log_info->pkt_length += record - temp;
}
void cnat_syslog_insert_record(
cnat_syslog_logging_info_t *log_info,
cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry,
cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type)
{
/* This record should like this -
* [EventName <L4> <Original Source IP> <Inside VRF Name>
* <Original Source IPv6> < Translated Source IP> <Original Port>
* <Translated First Source Port> <Translated Last Source Port>
* <Destination ip address> <destination port>]
*/
u32 original_source = db->in2out_key.k.ipv4;
u32 translated_ip = db->out2in_key.k.ipv4;
cnat_user_db_entry_t *udb = cnat_user_db + db->user_index;
unsigned char *temp, *record;
u32 network_order_ipv6[4];
temp = record = &(log_info->current_logging_context->packet_data[
CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
if (PREDICT_FALSE(!udb)) {
SYSLOG_DEBUG_PRINTF1("\nnull udb!");
return;
}
/* Now we point to the location where record needs to be inserted */
*record++ = '['; /* Open the record */
/* Copy the record type */
clib_memcpy(record, sys_log_event[e_type].event_name,
sys_log_event[e_type].name_length);
record += sys_log_event[e_type].name_length;
*record++ = SYSLOG_DELIMITER;
/* Copy the Protocol type */
if(PREDICT_FALSE(
e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
u16 my_proto_mask;
my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK;
if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
*record++ = '6';
} else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
*record++ = '1';
*record++ = '7';
} else {
*record++ = '1';
}
} else {
*record++ = SYSLOG_FIELD_ABSENT;
}
*record++ = SYSLOG_DELIMITER;
/* Copy the Original Source IP */
#ifdef DSLITE_USER_IPV4
record += copy_ipv4_addr(record, original_source);
#else
/*
* Do not include inside ipv4 address for B4 element level port limiting
*/
*record++ = SYSLOG_FIELD_ABSENT;
#endif
*record++ = SYSLOG_DELIMITER;
/* copy configured VRF NAME */
clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
record += log_info->vrf_name_len;
*record++ = SYSLOG_DELIMITER;
/* Copy the IPV6 source address */
/* CSCtt16960 Fix. */
network_order_ipv6[0] = htonl(udb->ipv6[0]);
network_order_ipv6[1] = htonl(udb->ipv6[1]);
network_order_ipv6[2] = htonl(udb->ipv6[2]);
network_order_ipv6[3] = htonl(udb->ipv6[3]);
inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN);
record += strlen(record);
*record++ = SYSLOG_DELIMITER;
/* Copy the translated IP address */
record += copy_ipv4_addr(record, translated_ip);
*record++ = SYSLOG_DELIMITER;
/* Copy the Original port */
if(e_type == sessionbased_assign || e_type == sessionbased_withdraw ||
e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) {
record += u16_to_ascii_decimal_unaligned(
record, db->in2out_key.k.port);
} else {
*record++ = SYSLOG_FIELD_ABSENT;
}
*record++ = SYSLOG_DELIMITER;
/* Copy the start outside port */
record += u16_to_ascii_decimal_unaligned(record, bulk_alloc);
*record++ = SYSLOG_DELIMITER;
/* Copy the last outside port */
if(e_type == userbased_assign || e_type == userbased_withdraw) {
record += u16_to_ascii_decimal_unaligned(record,
(bulk_alloc + BULKSIZE_FROM_VRFMAP(dslite_entry) - 1));
} else {
*record++ = SYSLOG_FIELD_ABSENT;
}
*record++ = SYSLOG_DELIMITER;
if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) {
if(sdb == NULL) {
record += copy_ipv4_addr(record, db->dst_ipv4);
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(record, db->dst_port);
} else {
record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4);
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port);
}
} else {
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = '-';
}
*record++ = SYSLOG_DELIMITER;
*record++ = ']'; /* End of the reocrd */
log_info->pkt_length += record - temp;
}
#define SYSLOG_PRECHECK(entry, s_type) \
if(PREDICT_FALSE((entry)->syslog_logging_index == EMPTY)) { \
SYSLOG_DEBUG_PRINTF1("\n1. Log Mapping failed") \
return; \
} \
logging_info = \
cnat_syslog_logging_info_pool + (entry)->syslog_logging_index; \
if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \
cnat_syslog_create_logging_context(logging_info, s_type); \
if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \
SYSLOG_DEBUG_PRINTF1("\n2. Log Mapping failed") \
return; \
} \
}
void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db,
cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb
#ifndef NO_BULK_LOGGING
, int bulk_alloc
#endif
)
{
cnat_syslog_logging_info_t *logging_info = 0;
syslog_event_type_t e_type;
int start_port;
SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
SYSLOG_PRECHECK(vrfmap, NAT44)
#ifndef NO_BULK_LOGGING
if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
e_type = userbased_assign;
start_port = bulk_alloc;
} else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
return; /* No logging required.. bulk port usage */
}
else { /* Individual logging .. fall back to old method */
#endif
if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) {
e_type = sessionbased_assignD;
} else {
e_type = sessionbased_assign;
}
start_port = db->out2in_key.k.port;
#ifndef NO_BULK_LOGGING
}
#endif
cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb,
start_port, e_type);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db,
dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb
#ifndef NO_BULK_LOGGING
, int bulk_alloc
#endif
)
{
cnat_syslog_logging_info_t *logging_info = 0;
syslog_event_type_t e_type;
int start_port;
SYSLOG_PRECHECK(dslite_entry, DSLite)
#ifndef NO_BULK_LOGGING
if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
e_type = userbased_assign;
start_port = bulk_alloc;
} else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
return; /* No logging required.. bulk port usage */
}
else { /* Individual logging .. fall back to old method */
#endif
if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) {
e_type = sessionbased_assignD;
} else {
e_type = sessionbased_assign;
}
start_port = db->out2in_key.k.port;
#ifndef NO_BULK_LOGGING
}
#endif
cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb,
start_port, e_type);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db,
cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb
#ifndef NO_BULK_LOGGING
, int bulk_alloc
#endif
)
{
cnat_syslog_logging_info_t *logging_info = 0;
syslog_event_type_t e_type;
int start_port;
SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__);
SYSLOG_PRECHECK(vrfmap, NAT44)
#ifndef NO_BULK_LOGGING
if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
e_type = userbased_withdraw;
start_port = bulk_alloc;
} else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
return; /* No logging required.. bulk port usage */
}
else { /* Individual logging .. fall back to old method */
#endif
if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) {
e_type = sessionbased_withdrawD;
} else {
e_type = sessionbased_withdraw;
}
start_port = db->out2in_key.k.port;
#ifndef NO_BULK_LOGGING
}
#endif
cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb,
start_port, e_type);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
void cnat_syslog_ds_lite_mapping_delete(cnat_main_db_entry_t *db,
dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb
#ifndef NO_BULK_LOGGING
, int bulk_alloc
#endif
)
{
cnat_syslog_logging_info_t *logging_info = 0;
syslog_event_type_t e_type;
int start_port;
SYSLOG_PRECHECK(dslite_entry, DSLite)
#ifndef NO_BULK_LOGGING
if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */
e_type = userbased_withdraw;
start_port = bulk_alloc;
} else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) {
return; /* No logging required.. bulk port usage */
}
else { /* Individual logging .. fall back to old method */
#endif
if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) {
e_type = sessionbased_withdrawD;
} else {
e_type = sessionbased_withdraw;
}
start_port = db->out2in_key.k.port;
#ifndef NO_BULK_LOGGING
}
#endif
cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb,
start_port, e_type);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
void cnat_syslog_dslite_insert_port_exceeded(
cnat_syslog_logging_info_t *log_info,
dslite_key_t * key)
{
/* This record should like this -
* [Portblockrunout <L4> <Original Source IP> <Inside VRF Name>
* <Original Source IPv6> - <Original Port> - - - -]
*/
u32 network_order_ipv6[4];
unsigned char *temp, *record;
temp = record = &(log_info->current_logging_context->packet_data[
CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
/* Now we point to the location where record needs to be inserted */
*record++ = '['; /* Open the record */
/* Copy the record type */
clib_memcpy(record, sys_log_event[port_block_runout].event_name,
sys_log_event[port_block_runout].name_length);
record += sys_log_event[port_block_runout].name_length;
*record++ = SYSLOG_DELIMITER;
u16 my_proto_mask;
my_proto_mask = key->ipv4_key.k.vrf & CNAT_PRO_MASK;
if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
*record++ = '6';
} else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
*record++ = '1';
*record++ = '7';
} else {
*record++ = '1';
}
*record++ = SYSLOG_DELIMITER;
/* Copy the Original Source IP */
record += copy_ipv4_addr(record, key->ipv4_key.k.ipv4);
*record++ = SYSLOG_DELIMITER;
/* copy configured VRF NAME */
clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
record += log_info->vrf_name_len;
*record++ = SYSLOG_DELIMITER;
/* Copy the IPV6 source address */
network_order_ipv6[0] = htonl(key->ipv6[0]);
network_order_ipv6[1] = htonl(key->ipv6[1]);
network_order_ipv6[2] = htonl(key->ipv6[2]);
network_order_ipv6[3] = htonl(key->ipv6[3]);
inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN);
record += strlen(record);
*record++ = SYSLOG_DELIMITER;
*record++ = SYSLOG_FIELD_ABSENT; /* No translated source ip */
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(
record, key->ipv4_key.k.port);
*record++ = SYSLOG_DELIMITER;
*record++ = SYSLOG_FIELD_ABSENT; /* No translated start port */
*record++ = SYSLOG_DELIMITER;
*record++ = SYSLOG_FIELD_ABSENT; /* No translated end port */
*record++ = SYSLOG_DELIMITER;
/*No Destination Info*/
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = ']'; /* End of the reocrd */
log_info->pkt_length += record - temp;
}
void cnat_syslog_ds_lite_port_limit_exceeded(
dslite_key_t * key,
dslite_table_entry_t *dslite_entry)
{
cnat_syslog_logging_info_t *logging_info = 0;
SYSLOG_PRECHECK(dslite_entry, DSLite)
cnat_syslog_dslite_insert_port_exceeded(logging_info, key);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
void cnat_syslog_nat44_insert_port_exceeded(
cnat_syslog_logging_info_t *log_info,
cnat_key_t * key)
{
/* This record should like this -
* [Portblockrunout <L4> <Original Source IP> <Inside VRF Name>
* - - <Original Port> - - - -]
*/
unsigned char *temp, *record;
temp = record = &(log_info->current_logging_context->packet_data[
CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
/* Now we point to the location where record needs to be inserted */
*record++ = '['; /* Open the record */
/* Copy the record type */
clib_memcpy(record, sys_log_event[port_block_runout].event_name,
sys_log_event[port_block_runout].name_length);
record += sys_log_event[port_block_runout].name_length;
*record++ = SYSLOG_DELIMITER;
u16 my_proto_mask;
my_proto_mask = key->k.vrf & CNAT_PRO_MASK;
if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) {
*record++ = '6';
} else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) {
*record++ = '1';
*record++ = '7';
} else {
*record++ = '1';
}
*record++ = SYSLOG_DELIMITER;
/* Copy the Original Source IP */
record += copy_ipv4_addr(record, key->k.ipv4);
*record++ = SYSLOG_DELIMITER;
/* copy configured VRF NAME */
clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
record += log_info->vrf_name_len;
*record++ = SYSLOG_DELIMITER;
/* No IPV6 source address for nat44 */
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = '-'; /* No translated source ip */
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(
record, key->k.port);
*record++ = SYSLOG_DELIMITER;
*record++ = '-'; /* No translated start port */
*record++ = SYSLOG_DELIMITER;
*record++ = '-'; /* No translated end port */
*record++ = SYSLOG_DELIMITER;
/*No Destination Info*/
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = ']'; /* End of the reocrd */
log_info->pkt_length += record - temp;
}
void cnat_syslog_nat44_port_limit_exceeded(
cnat_key_t * key,
cnat_vrfmap_t *vrfmap)
{
cnat_syslog_logging_info_t *logging_info = 0;
SYSLOG_PRECHECK(vrfmap, NAT44)
cnat_syslog_nat44_insert_port_exceeded(logging_info, key);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
void cnat_syslog_nat44_insert_tcp_seq_mismatch(
cnat_syslog_logging_info_t *log_info,
cnat_main_db_entry_t *db)
{
/* This record should like this -
* [TCPseqmismatch <L4> <Original Source IP> <Inside VRF Name>
* - <Translated Source IP> <Original Port> <Translated Source Port> - - -]
*/
unsigned char *temp, *record;
temp = record = &(log_info->current_logging_context->packet_data[
CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]);
/* Now we point to the location where record needs to be inserted */
*record++ = '['; /* Open the record */
/* Copy the record type */
clib_memcpy(record, sys_log_event[tcp_seq_mismatch].event_name,
sys_log_event[tcp_seq_mismatch].name_length);
record += sys_log_event[tcp_seq_mismatch].name_length;
*record++ = SYSLOG_DELIMITER;
/* Next field is TCP */
*record++ = '6';
*record++ = SYSLOG_DELIMITER;
/* Copy the Original Source IP */
record += copy_ipv4_addr(record, db->in2out_key.k.ipv4);
*record++ = SYSLOG_DELIMITER;
/* copy configured VRF NAME */
clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len);
record += log_info->vrf_name_len;
*record++ = SYSLOG_DELIMITER;
/* No IPV6 source address for nat44 */
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
record += copy_ipv4_addr(record, db->out2in_key.k.ipv4);
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(
record, db->in2out_key.k.port);
*record++ = SYSLOG_DELIMITER;
record += u16_to_ascii_decimal_unaligned(
record, db->out2in_key.k.port);
*record++ = SYSLOG_DELIMITER;
*record++ = '-'; /* No translated end port */
*record++ = SYSLOG_DELIMITER;
/*No Destination Info*/
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = '-';
*record++ = SYSLOG_DELIMITER;
*record++ = ']'; /* End of the reocrd */
log_info->pkt_length += record - temp;
}
void cnat_syslog_nat44_tcp_seq_mismatch(
cnat_main_db_entry_t *db,
cnat_vrfmap_t *vrfmap)
{
cnat_syslog_logging_info_t *logging_info = 0;
SYSLOG_PRECHECK(vrfmap, NAT44)
cnat_syslog_nat44_insert_tcp_seq_mismatch(logging_info, db);
/*
* If we have exceeded the packet length, let us send the
* packet now. There is buffer of additional bytes beyond
* max_pkt_length to ensure that the last add/delete record
* can be stored safely.
*/
if (PREDICT_FALSE(logging_info->pkt_length >
logging_info->max_length_minus_max_record_size)) {
cnat_syslog_send_pkt(logging_info);
}
}
#endif