/* *------------------------------------------------------------------ * 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 #include "cnat_syslog.h" #include "platform_common.h" #include "cnat_db.h" #include "cnat_log_common.h" #include #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 * < Translated Source IP> * * ] */ 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 * < Translated Source IP> * * ] */ 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 * - - - - -] */ 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 * - - - - - -] */ 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 * - - - -] */ 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