summaryrefslogtreecommitdiffstats
path: root/common/VIL
diff options
context:
space:
mode:
authorVishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>2017-10-05 03:37:35 +0530
committerAnand B Jyoti <anand.b.jyoti@intel.com>2017-10-06 08:45:47 +0530
commitdfdeef016f8f2d4f14a3c01d183bff6170dcdbb9 (patch)
treea71278588d30257e00660fe9ee05708c392ac70e /common/VIL
parent2e53911bb32745221fdc077d06237abc44ad9962 (diff)
common code: KW fixes for common code
This patch fixes KW issues seen with the common code. Change-Id: I4f90369152345ea2ea9316b04ac946c0c69fd7d1 Signed-off-by: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
Diffstat (limited to 'common/VIL')
-rw-r--r--common/VIL/alg/lib_ftp_alg.c69
-rw-r--r--common/VIL/alg/lib_sip_alg.c23
-rw-r--r--common/VIL/l2l3_stack/lib_arp.c93
-rw-r--r--common/VIL/l2l3_stack/lib_icmpv6.c2
-rw-r--r--common/VIL/pipeline_arpicmp/pipeline_arpicmp.c18
-rw-r--r--common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c6
6 files changed, 147 insertions, 64 deletions
diff --git a/common/VIL/alg/lib_ftp_alg.c b/common/VIL/alg/lib_ftp_alg.c
index 7e8e43f1..f653de8b 100644
--- a/common/VIL/alg/lib_ftp_alg.c
+++ b/common/VIL/alg/lib_ftp_alg.c
@@ -174,7 +174,13 @@ populate_ftp_alg_entry(uint32_t ipaddr, uint8_t portid)
return;
}
new_alg_data = (struct ftp_alg_table_entry *)
- malloc(sizeof(new_alg_data));
+ malloc(sizeof(struct ftp_alg_table_entry));
+
+ if (!new_alg_data) {
+ printf("new_alg_data could not be allocated\n");
+ return;
+ }
+
//new_alg_data->status = INCOMPLETE;
new_alg_data->l4port = rte_bswap16(portid);
new_alg_data->ip_address = rte_bswap32(ipaddr);
@@ -482,18 +488,18 @@ void ftp_alg_dpi(
uint16_t private_port_number;
uint16_t public_port_number;
uint16_t ip1, ip2, ip3, ip4, port1, port2;
- int16_t tcpSeqdiff;
+ int16_t tcpSeqdiff = 0;
int16_t ackSeqdiff, ackAdjust;
uint32_t private_address;
uint32_t public_address;
uint8_t *bptr_private_address;
/* also for PASV string */
- char port_string[FTP_MAXIMUM_PORT_STRING_LENGTH];
+ char port_string[65];
char port_string_translated[FTP_MAXIMUM_PORT_STRING_LENGTH];
- int16_t new_port_string_length;
+ int16_t new_port_string_length = 0;
int16_t old_port_string_length;
int dummy_value;
- struct cgnapt_table_entry *egress_entry, *ingress_entry;
+ struct cgnapt_table_entry *egress_entry = NULL, *ingress_entry;
uint32_t ct_key[10];
uint8_t key_direction;
/*Since v6 is not supported now*/
@@ -597,7 +603,7 @@ void ftp_alg_dpi(
&ip1, &ip2, &ip3, &ip4, &port1, &port2) ==
FTP_PASV_PARAMETER_COUNT){
- sprintf (port_string, FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE,
+ snprintf (port_string, sizeof(port_string), FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE,
ip1, ip2, ip3, ip4, port1, port2);
int i = 0;
@@ -672,22 +678,25 @@ void ftp_alg_dpi(
((thdr->data_off & 0xf0) >> 2) - ip_hdr_size_bytes;
cgnat_cnxn_tracker->hash_table_entries[ct_position].
tcp_payload_size = tmp_tcp_paylod_size;
+ if(egress_entry) {
- /*Adding ALG entry , params to be derived from egress entry*/
- populate_ftp_alg_entry(egress_entry->data.pub_ip,
- egress_entry->data.pub_port);
- /* payload modification */
- new_port_string_length = ftp_alg_modify_payload(egress_entry,
- port_string,
- port_string_translated, 1);
- strncpy(tcp_header_end, port_string_translated,
- strlen(port_string_translated));
- tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
+ /*Adding ALG entry , params to be derived from egress entry*/
+ populate_ftp_alg_entry(egress_entry->data.pub_ip,
+ egress_entry->data.pub_port);
+
+ /* payload modification */
+ new_port_string_length = ftp_alg_modify_payload(egress_entry,
+ port_string,
+ port_string_translated, 1);
+ strncpy(tcp_header_end, port_string_translated,
+ strlen(port_string_translated));
+ tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
cgnat_cnxn_tracker->hash_table_entries
[ct_position].tcpSeqdiff,
old_port_string_length,
new_port_string_length);
+ }
/* same as rte_synproxy_adjust_pkt_length() in ct */
ftp_alg_modify_pkt_len(pkt);
/*
@@ -822,19 +831,21 @@ void ftp_alg_dpi(
tcp_payload_size = tmp_tcp_paylod_size;
/*ALG entry add, params to be derived from egress entry*/
- populate_ftp_alg_entry(egress_entry->data.pub_ip,
- egress_entry->data.pub_port);
- /* payload modification */
- new_port_string_length = ftp_alg_modify_payload(egress_entry,
- port_string,
- port_string_translated, 0);
- strncpy(tcp_header_end, port_string_translated,
- strlen(port_string_translated));
- tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
- cgnat_cnxn_tracker->hash_table_entries
- [ct_position].tcpSeqdiff,
- old_port_string_length,
- new_port_string_length);
+ if(egress_entry) {
+ populate_ftp_alg_entry(egress_entry->data.pub_ip,
+ egress_entry->data.pub_port);
+ /* payload modification */
+ new_port_string_length = ftp_alg_modify_payload(egress_entry,
+ port_string,
+ port_string_translated, 0);
+ strncpy(tcp_header_end, port_string_translated,
+ strlen(port_string_translated));
+ tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
+ cgnat_cnxn_tracker->hash_table_entries
+ [ct_position].tcpSeqdiff,
+ old_port_string_length,
+ new_port_string_length);
+ }
/* same as rte_synproxy_adjust_pkt_length() in ct */
ftp_alg_modify_pkt_len(pkt);
diff --git a/common/VIL/alg/lib_sip_alg.c b/common/VIL/alg/lib_sip_alg.c
index 9940d59a..0e281200 100644
--- a/common/VIL/alg/lib_sip_alg.c
+++ b/common/VIL/alg/lib_sip_alg.c
@@ -162,6 +162,7 @@ void lib_sip_alg_init(void)
}
char *itoa(long n);
+char itoa_buf[25];
char *itoa(long n)
{
int len = n == 0 ? 1 : floor(log10l(labs(n))) + 1;
@@ -169,10 +170,8 @@ char *itoa(long n)
if (n < 0)
len++; /* room for negative sign '-' */
- char *buf = calloc(sizeof(char), len + 1); // +1 for null
- if(buf != NULL)
- snprintf(buf, len + 1, "%ld", n);
- return buf;
+ snprintf(itoa_buf, len + 1, "%ld", n);
+ return (char *)&itoa_buf;
}
struct sip_alg_table_entry *retrieve_sip_alg_entry(
@@ -340,6 +339,10 @@ int sip_alg_dpi(struct rte_mbuf *pkt, enum pkt_dir pkt_direction,
sip_call_id =
getSipCallIdStr(pSipMsg + pos +
TAG_TO_DATAPOS(SIP_ALG_CALLID));
+ if (!sip_call_id) {
+ printf("sip_call_id returned is NULL\n");
+ return 0;
+ }
if (ALG_DEBUG)
printf("sipalgdpi: %d call id %s\n", __LINE__,
@@ -572,6 +575,9 @@ char *sip_alg_process(struct rte_mbuf *pkt, uint16_t pkt_direction,
int sipMsgLen = (pTmpSipMsg - pSipMsg);
+ if ((sipMsgLen + sdpDataLen) > strlen(pSipMsg))
+ return NULL;
+
char *pSipMsgEnd = pSipMsg + sipMsgLen + sdpDataLen;
if (ALG_DEBUG)
@@ -1889,7 +1895,11 @@ SipMsgAdvance2:
sdpMsgLen += sdpDataLen;
tmpSdpLen = itoa(sdpMsgLen);
- int tmpStrLen = strlen(tmpSdpLen);
+ int tmpStrLen;
+ if (tmpSdpLen)
+ tmpStrLen = strlen(tmpSdpLen);
+ else
+ tmpStrLen = 0;
/* move to Content length field & change the length to sipMsgLen */
if (natSipAlgMsgFieldPos(pSipMsg, SIP_ALG_CONTENT_LEN, &pos, 0)
@@ -2225,6 +2235,9 @@ char *natSipAlgModifyPayloadAddrPort(
if (newStrLen > oldStrLen)
*diffLen = newStrLen - oldStrLen;
+ if (tmpPort)
+ free(tmpPort);
+
return pSipMsg; /* modified SIP Msg */
}
diff --git a/common/VIL/l2l3_stack/lib_arp.c b/common/VIL/l2l3_stack/lib_arp.c
index 42a619d7..39a740dd 100644
--- a/common/VIL/l2l3_stack/lib_arp.c
+++ b/common/VIL/l2l3_stack/lib_arp.c
@@ -294,13 +294,20 @@ struct arp_entry_data *get_dest_mac_addr_ipv4(const uint32_t nhip,
uint32_t phy_port, struct ether_addr *hw_addr)
{
struct arp_entry_data *ret_arp_data = NULL;
+ struct ether_addr *x;
uint8_t index;
/* as part of optimization we store mac address in cache
* & thus can be sent without having to retrieve
*/
if (arp_cache_dest_mac_present(phy_port)) {
- ether_addr_copy(get_local_cache_hw_addr(phy_port, nhip), hw_addr);
+ x = get_local_cache_hw_addr(phy_port, nhip);
+ if (!x) {
+ printf("local copy of address not stored\n");
+ return NULL;
+ }
+
+ ether_addr_copy(x, hw_addr);
return &arp_entry_data_default;
}
@@ -352,11 +359,17 @@ struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[],
struct nd_entry_data *ret_nd_data = NULL;
struct nd_key_ipv6 tmp_nd_key;
+ struct ether_addr *addr;
tmp_nd_key.port_id = phy_port;
if (nd_cache_dest_mac_present(phy_port)) {
- ether_addr_copy(get_nd_local_link_hw_addr(
- (uint8_t)phy_port, nhipv6), hw_addr);
+ addr = get_nd_local_link_hw_addr((uint8_t)phy_port, nhipv6);
+ if (!addr) {
+ printf("local copy not stored\n");
+ return NULL;
+ }
+
+ ether_addr_copy(addr, hw_addr);
return &nd_entry_data_default;
}
@@ -743,6 +756,7 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m
struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
{
struct nd_entry_data *ret_nd_data = NULL;
+ l2_phy_interface_t *port;
nd_key.filler1 = 0;
nd_key.filler2 = 0;
nd_key.filler3 = 0;
@@ -822,7 +836,14 @@ struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
ret_nd_data->timer_key = callback_key;
/* send nd request */
- request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
+ port = ifm_get_port(callback_key->port_id);
+ if (!port) {
+ printf("port returned is NULL inside retrieve_nd_entry\n");
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ return NULL;
+ }
+
+ request_nd(callback_key->ipv6, port);
rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
} else {
if (ret_nd_data &&
@@ -849,7 +870,14 @@ struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
ret_nd_data->timer_key = callback_key;
/* send nd request */
- request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
+ port = ifm_get_port(callback_key->port_id);
+ if (!port) {
+ printf("port returned is NULL inside retrieve_nd_entry\n");
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ return NULL;
+ }
+
+ request_nd(callback_key->ipv6, port);
rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
}
}
@@ -911,7 +939,7 @@ void print_arp_table(void)
lib_arp_populate_called, lib_arp_delete_called,
lib_arp_duplicate_found);
- printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
+ printf("ARP table key len is %d\n", (uint32_t) sizeof(struct arp_key_ipv4));
}
/* ND IPv6 */
@@ -974,7 +1002,7 @@ void print_nd_table(void)
lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
lib_nd_populate_called, lib_nd_delete_called,
lib_nd_duplicate_found);
- printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
+ printf("ND table key len is %d\n\n", (uint32_t) sizeof(struct nd_key_ipv6));
}
void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
@@ -1052,7 +1080,7 @@ arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
int i;
- if (!hw_addr || !ret_arp_data)
+ if (!hw_addr || !ret_arp_data || !port)
return;
rte_rwlock_write_lock(&ret_arp_data->queue_lock);
@@ -1097,7 +1125,7 @@ nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
uint8_t *eth_dest, *eth_src;
int i;
- if (!hw_addr || !ret_nd_data)
+ if (!hw_addr || !ret_nd_data || !port)
return;
rte_rwlock_write_lock(&ret_nd_data->queue_lock);
@@ -1193,8 +1221,8 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
} else {
rte_rwlock_write_lock(&new_arp_data->queue_lock);
ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
- if ((new_arp_data->status == INCOMPLETE) ||
- (new_arp_data->status == PROBE)) {
+ if (new_arp_data && ((new_arp_data->status == INCOMPLETE) ||
+ (new_arp_data->status == PROBE))) {
new_arp_data->status = COMPLETE;
new_arp_data->mode = mode;
new_arp_data->n_confirmed = rte_rdtsc();
@@ -1295,6 +1323,7 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
uint8_t i, val = 0;
struct nd_key_ipv6 nd_key;
nd_key.port_id = portid;
+ l2_phy_interface_t *port;
for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
nd_key.ipv6[i] = ipv6[i];
@@ -1342,8 +1371,10 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
if (new_nd_data->status == STALE) {
new_nd_data->retry_count = 0; // Reset
new_nd_data->status = PROBE;
- request_nd(new_nd_data->ipv6,
- ifm_get_port(new_nd_data->port));
+ port = ifm_get_port(new_nd_data->port);
+
+ if (port)
+ request_nd(new_nd_data->ipv6, port);
if (rte_timer_reset(new_nd_data->timer,
(arp_timeout * rte_get_tsc_hz()),
@@ -1360,8 +1391,8 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
} else {
rte_rwlock_write_lock(&new_nd_data->queue_lock);
ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
- if ((new_nd_data->status == INCOMPLETE) ||
- (new_nd_data->status == PROBE)) {
+ if (new_nd_data && ((new_nd_data->status == INCOMPLETE) ||
+ (new_nd_data->status == PROBE))) {
new_nd_data->status = COMPLETE;
new_nd_data->mode = mode;
new_nd_data->n_confirmed = rte_rdtsc();
@@ -2092,6 +2123,12 @@ static int arp_parse_args(struct pipeline_params *params)
RTE_SET_USED(nd_route_tbl_present);
RTE_SET_USED(arp_route_tbl_present);
for (numArg = 0; numArg < params->n_args; numArg++) {
+
+ if(strlen(params->args_value[numArg]) > PIPELINE_MAX_ARGS) {
+ /* KW Fix */
+ printf("WARNING: Non-Null terminated Parameter not processed\n");
+ continue;
+ }
char *arg_name = params->args_name[numArg];
char *arg_value = params->args_value[numArg];
@@ -2192,12 +2229,15 @@ static int arp_parse_args(struct pipeline_params *params)
tx_phy_port_num, txport);
if ((rxport >= PIPELINE_MAX_PORT_IN) ||
- (txport >= PIPELINE_MAX_PORT_IN) ||
- (in_port_dir_a[rxport] != 1)) {
+ (txport >= PIPELINE_MAX_PORT_IN)) {
printf
- ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
- rxport, txport,
- in_port_dir_a[rxport]);
+ ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d\n",
+ rxport, txport);
+ return -1;
+ }
+
+ if (in_port_dir_a[rxport] != 1) {
+ printf("CG-NAPT parse error - incorrect rx_port supplied\n");
return -1;
}
@@ -2271,6 +2311,10 @@ static int arp_parse_args(struct pipeline_params *params)
}
tx_port_str[k] = '\0';
tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
+ if (tx_port > MAX_ROUTE_ENTRY_SIZE) {
+ printf("tx_port is greater than route entry max size\n");
+ continue;
+ }
k++;
l = 0;
@@ -2710,6 +2754,7 @@ void nd_timer_callback(struct rte_timer *timer, void *arg)
int j;
struct nd_entry_data *ret_nd_data = NULL;
uint64_t now;
+ l2_phy_interface_t *port;
nd_key.port_id = timer_key->port_id;
nd_key.filler1 = 0;
@@ -2755,9 +2800,13 @@ void nd_timer_callback(struct rte_timer *timer, void *arg)
"TIMER STARTED FOR %u seconds\n",
ARP_TIMER_EXPIRY);
}
+ port = ifm_get_port(ret_nd_data->port);
+ if (!port) {
+ printf("port is NULL in nd_timer_callback\n");
+ return;
+ }
- request_nd(ret_nd_data->ipv6,
- ifm_get_port(ret_nd_data->port));
+ request_nd(ret_nd_data->ipv6, port);
if (rte_timer_reset(ret_nd_data->timer,
(PROBE_TIME *
rte_get_tsc_hz()/ 1000),
diff --git a/common/VIL/l2l3_stack/lib_icmpv6.c b/common/VIL/l2l3_stack/lib_icmpv6.c
index eea67b0d..d516717e 100644
--- a/common/VIL/l2l3_stack/lib_icmpv6.c
+++ b/common/VIL/l2l3_stack/lib_icmpv6.c
@@ -363,7 +363,7 @@ struct rte_mbuf *request_nd(uint8_t ipv6[], l2_phy_interface_t *port)
int i;
struct rte_mbuf *icmpv6_pkt = lib_nd_pkt[port->pmdid];
- if (icmpv6_pkt == NULL) {
+ if ((icmpv6_pkt == NULL) || (port == NULL)) {
if (ARPICMP_DEBUG)
printf("Error allocating icmpv6_pkt rte_mbuf\n");
return NULL;
diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c
index 607d13d1..847e2936 100644
--- a/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c
+++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c
@@ -70,10 +70,10 @@ struct cmd_arp_add_result {
};
-uint16_t str2flowtype(char *string);
+uint16_t str2flowtype(const char *string);
int parse_flexbytes(const char *q_arg, uint8_t *flexbytes,
uint16_t max_num);
-enum rte_eth_input_set_field str2inset(char *string);
+enum rte_eth_input_set_field str2inset(const char *string);
int app_pipeline_arpicmp_entry_dbg(struct app_params *app,
uint32_t pipeline_id, uint8_t *msg);
@@ -168,6 +168,11 @@ cmd_arp_del_parsed(void *parsed_result,
arp_key.filler2 = 0;
arp_key.filler3 = 0;
struct arp_entry_data *new_arp_data = retrieve_arp_entry(arp_key, STATIC_ARP);
+ if(new_arp_data == NULL) {
+ /* KW Fix */
+ printf("Retrieve arp returned NULL\n");
+ return;
+ }
remove_arp_entry(new_arp_data, &arp_key);
} else {
struct nd_key_ipv6 nd_key;
@@ -177,6 +182,11 @@ cmd_arp_del_parsed(void *parsed_result,
nd_key.filler2 = 0;
nd_key.filler3 = 0;
struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, STATIC_ND);
+ if(new_nd_data == NULL) {
+ /* KW Fix */
+ printf("Retrieve ND returned NULL\n");
+ return;
+ }
remove_nd_entry_ipv6(new_nd_data, &nd_key);
}
}
@@ -960,7 +970,7 @@ cmdline_parse_inst_t cmd_set_fwd_mode = {
#if 1
-uint16_t str2flowtype(char *string)
+uint16_t str2flowtype(const char *string)
{
uint8_t i = 0;
static const struct {
@@ -1450,7 +1460,7 @@ struct cmd_set_hash_input_set_result {
};
enum rte_eth_input_set_field
-str2inset(char *string)
+str2inset(const char *string)
{
uint16_t i;
diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c
index 481f8521..61768130 100644
--- a/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c
+++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c
@@ -210,7 +210,7 @@ void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p)
switch (myApp->pipeline_params[pipeline_num].
pktq_in[port_count].type){
- case APP_PKTQ_OUT_HWQ:
+ case APP_PKTQ_IN_HWQ:
hwq = rte->ports_in[port_count].h_port;
out_swq = rte->ports_out[port_count].h_port;
printf("out_swq: %s\n",
@@ -230,7 +230,7 @@ void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p)
}
break;
- case APP_PKTQ_OUT_SWQ:
+ case APP_PKTQ_IN_SWQ:
in_swq = rte->ports_in[port_count].h_port;
out_swq = rte->ports_out[port_count].h_port;
printf("in_swq : %s\n",
@@ -432,7 +432,7 @@ void set_phy_inport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
switch (myApp->pipeline_params[pipeline_num].
pktq_in[port_count].type) {
- case APP_PKTQ_OUT_HWQ:
+ case APP_PKTQ_IN_HWQ:
hwq = rte->ports_in[port_count].h_port;
map[hwq->port_id] = index++;
printf("outport_id[%d]:%d\n", index - 1,