/*
 *
 *  Copyright (C) 2007 Mindspeed Technologies, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <net/if.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include "cmm.h"
#include "cmmd.h"
#include "module_mc6.h"

#define MC6_MAX_LISTENERS_IN_QUERY     5

unsigned char Null_Mac[6] = {0,0,0,0,0,0};

extern pthread_mutex_t mc_lock;

int cmmMc6Show(struct cli_def * cli, char *command, char *argv[], int argc)
{
	int count = 0, ii, jj;
	struct list_head *entry;
	struct mcast_entry *mc;
        char buf1[INET6_ADDRSTRLEN];
        char buf2[INET6_ADDRSTRLEN];

	__pthread_mutex_lock(&mc_lock);
	
	for( ii = 0; ii < MC_NUM_HASH_ENTRIES; ii++ )
	{
		for (entry = list_first(&mc_table[ii]); entry != &mc_table[ii]; entry = list_next(entry))
		{
			mc = container_of(entry, struct mcast_entry, list);
			
			if( mc->family != AF_INET6 )
				continue;
			
                	 cmm_print(DEBUG_STDOUT, "%04d: Src addr: %s  src_mask_len: %x   Dst addr: %s Queue %d  \n",
			  count,
			  inet_ntop(AF_INET6, &mc->src_addr, buf1, INET6_ADDRSTRLEN),
			  mc->src_mask_len,
			  inet_ntop(AF_INET6, &mc->dst_addr, buf2, INET6_ADDRSTRLEN),
                          mc->queue);
		  	for( jj = 0; jj < mc->num_output; jj++) 	
			{
				cmm_print(DEBUG_STDOUT," PROGRAMMED : %02d TIMER : 0x%x   SHAPER : 0x%x  Interface %s\n",mc->l_program[jj],
					mc->listener[jj].timer,mc->listener[jj].shaper_mask, mc->listener[jj].output_device_str);
				if(mc->listener[jj].q_bit)
					cmm_print(DEBUG_STDOUT," QUEUE : 0x%x  \n",mc->listener[jj].queue );
				if(mc->listener[jj].uc_bit)
					cmm_print(DEBUG_STDOUT,"UC MAC is %02x:%02x:%02x:%02x:%02x:%02x  ",mc->listener[jj].uc_mac[0],mc->listener[jj].uc_mac[1],mc->listener[jj].uc_mac[2],mc->listener[jj].uc_mac[3],mc->listener[jj].uc_mac[4],mc->listener[jj].uc_mac[5]);
			}	
			count++;	
				
		}
	}  
        cmm_print(DEBUG_STDOUT, "Total Multicast v6 Entries: %d\n", count);
	__pthread_mutex_unlock(&mc_lock);
	
	return 0;
}

/************************************************************
 *
 *
 *
 ************************************************************/
void cmmMc6ShowPrintHelp()
{
	cmm_print(DEBUG_STDOUT, "show mc6 not yet supported\n");
}


/************************************************************
 *
 *
 *
 ************************************************************/
int cmmMc6ShowProcess(char ** keywords, int tabStart, daemon_handle_t daemon_handle)
{
	
//help:
	cmmMc6ShowPrintHelp();
	return -1;
}

/************************************************************
 *
 *
 *
 ************************************************************/
int cmmMc6QueryProcess(char ** keywords, int tabStart, daemon_handle_t daemon_handle)
{
	
        int rcvBytes = 0;
        char rcvBuffer[256];
        char buf1[INET6_ADDRSTRLEN];
        char buf2[INET6_ADDRSTRLEN];
	char output_buf[256];
        short rc;
        int count = 0,len =0;
        cmmd_mc6_entry_t *mc6_entry = (cmmd_mc6_entry_t *) rcvBuffer;
        cmmd_mc6_listener_t* mc6_listener = (cmmd_mc6_listener_t *)(rcvBuffer + sizeof (cmmd_mc6_entry_t));

        mc6_entry->action = CMMD_ACTION_QUERY;
        rcvBytes = cmmSendToDaemon(daemon_handle,CMMD_CMD_MC6_MULTICAST ,
                  mc6_entry, sizeof(cmmd_mc6_entry_t)+ MC6_MAX_LISTENERS_IN_QUERY * sizeof(cmmd_mc6_listener_t) , rcvBuffer);

        if (rcvBytes < sizeof(cmmd_mc6_entry_t) + sizeof (cmmd_mc6_listener_t) + sizeof(unsigned short)) {
                rc = (rcvBytes < sizeof(unsigned short) ) ? 0 : *((unsigned short *) rcvBuffer);
                if (rc == CMMD_ERR_UNKNOWN_ACTION) {
                    cmm_print(DEBUG_STDERR, "ERROR: FPP CMD_MC6_MULTICAST does not support ACTION_QUERY\n");
                } else if (rc == CMMD_ERR_MC_ENTRY_NOT_FOUND) {
                    cmm_print(DEBUG_STDERR, "ERROR: FPP Multicast V6 table empty\n");
                } else {
                    cmm_print(DEBUG_STDERR, "ERROR: Unexpected result returned from FPP rc:%d\n", rc);
                }
                return CLI_OK;
            }
            cmm_print(DEBUG_STDOUT, "IPv6 Multicast Entries:\n");
            do {
                int i, listner_count;
		if(mc6_entry->dst_addr[0] & 0xFF)
		{
	                cmm_print(DEBUG_STDOUT, "\n%04d: Src addr: %s  src_mask_len: %x   Dst addr: %s   Queue: 0x%x \n\n",
        	                  count,
                	          inet_ntop(AF_INET6, &mc6_entry->src_addr, buf1, INET6_ADDRSTRLEN),
                        	  mc6_entry->src_mask_len,
	                          inet_ntop(AF_INET6, &mc6_entry->dst_addr, buf2, INET6_ADDRSTRLEN),
				  mc6_entry->queue );
			count++;
		}
                listner_count = mc6_entry->num_output;
                if (listner_count > MC6_MAX_LISTENERS_IN_QUERY)
                {
                        cmm_print(DEBUG_STDOUT,"output interfaces are more than %d",MC6_MAX_LISTENERS_IN_QUERY);
                        listner_count = MC6_MAX_LISTENERS_IN_QUERY;
                }

                for ( i = 0; i < listner_count; i++)
		{
	            len += sprintf(output_buf + len, "output interface:  ");
                    len += sprintf(output_buf + len, "%s  ", mc6_listener[i].output_device_str);
		    cmm_print (DEBUG_STDOUT,output_buf);
                    if(mc6_listener[i].uc_bit)
                           cmm_print(DEBUG_STDOUT,"UC MAC is %02x:%02x:%02x:%02x:%02x:%02x  ",mc6_listener[i].uc_mac[0],mc6_listener[i].uc_mac[1],mc6_listener[i].uc_mac[2],mc6_listener[i].uc_mac[3],mc6_listener[i].uc_mac[4],mc6_listener[i].uc_mac[5]);
                   cmm_print(DEBUG_STDOUT," TIMER : 0x%x   SHAPER : 0x%x   QUEUE : 0x%x\n",mc6_listener[i].timer,mc6_listener[i].shaper_mask, mc6_listener[i].queue);
                   len = 0;
		}

                mc6_entry->action = CMMD_ACTION_QUERY_CONT;
                rcvBytes = cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_MULTICAST, mc6_entry,
                                          sizeof(cmmd_mc6_entry_t)+ MC6_MAX_LISTENERS_IN_QUERY * sizeof(cmmd_mc6_listener_t), rcvBuffer);
            } while (rcvBytes >= sizeof(cmmd_mc6_entry_t)+ sizeof(cmmd_mc6_listener_t) + sizeof(unsigned short));
            cmm_print(DEBUG_STDOUT, "Total Multicast v6 Entries: %d\n", count);

        return CLI_OK;

}


/************************************************************
 *
 *
 *
 ************************************************************/
void cmmMc6SetPrintHelp()
{
#ifdef COMCERTO_2000	
	cmm_print(DEBUG_STDOUT, "Usage: set mc6 interface {if_name} {add | del | update } \n\tgroup {bit_mask} {IPv6 Src Address} {IPv6 Multicast Dst Address} [mode {bridged | routed}] [queue {0..19}] \n\t[listener [timer {timer_value1}] [shapers {0..0xFF}][mc | uc {Mac addr1} ] [queue {0..19}]] [if {if_name}] \n\t [ listener [timer {timer_value2}]  [shapers {0..0xFF}][mc | uc {Mac addr2} ] [queue {0..19}]] [if {if_name}]...  \n\t[ listener [timer {timer_valueN}]  [shapers {0..0xFF}][mc | uc {Mac addrN} ] [queue {0..19}]] [if {if_name}]");
#else
	cmm_print(DEBUG_STDOUT, "Usage: set mc6 interface {if_name} {add | del | update } \n\tgroup {bit_mask} {IPv6 Src Address} {IPv6 Multicast Dst Address} [mode {bridged | routed}] [queue {0..31}]\n\t[listener [timer {timer_value1}] [shapers {0..0xFF}][mc | uc {Mac addr1} ] [queue {0..31}]] [if {if_name}] \n\t [ listener [timer {timer_value2}]  [shapers {0..0xFF}][mc | uc {Mac addr2} ] [queue {0..31}]] [if {if_name}]...  \n\t[ listener [timer {timer_valueN}]  [shapers {0..0xFF}][mc | uc {Mac addrN} ] [queue {0..31}]] [if {if_name}] ");
#endif
	cmm_print(DEBUG_STDOUT, "\n\nUsage:set mc6 mode route|bridge\n");
}

/************************************************************
 * cmmMc6ParseListener
 * This function parses the mc6 command with multiple listeners
 * and a single listener alike.
 *
 ************************************************************/
int cmmMcParseListener(char ** keywords, int *cpt, cmmd_mc6_listener_t * listener, u_int8_t * mode, u_int16_t action)
{

	unsigned int tmp;
	char * endptr;
	
	listener->timer = 0xFFFFFFFF;
	listener->q_bit = 0;
	listener->uc_bit = 0; // Multicast by default when a new entry is added
	listener->Ifbit = 0;
	
	while(keywords[*cpt] && (strncasecmp(keywords[*cpt],"listener",strlen(keywords[*cpt])) != 0))
	{
		if(strcasecmp(keywords[*cpt],"mc") == 0)
		{
			listener->uc_bit = 0;
		}
		else if(strcasecmp(keywords[*cpt],"uc") == 0)
		{
			if(!keywords[++*cpt])
				return 1;
			listener->uc_bit = 1;
			if (!parse_macaddr(keywords[*cpt], listener->uc_mac))
			{
				cmm_print(DEBUG_STDERR, "ERROR %d Invalid Mac Address \n",CMMD_ERR_MC_INVALID_MAC);
				return 1;
			}
			if((listener->uc_mac[0] & 0x01) || !memcmp(listener->uc_mac,Null_Mac,6))
			{
				cmm_print(DEBUG_STDERR, "ERROR %d Invalid Mac Address \n",CMMD_ERR_MC_INVALID_MAC);
				return 1;
			}
		}

		else if (strcasecmp(keywords[*cpt], "timer") == 0)
		{
			if(!keywords[++*cpt])
				return 1;

			/*Get an integer from the string*/
			endptr = NULL;
			tmp = strtoul(keywords[*cpt], &endptr, 0);
			listener->timer = tmp;
		}
		else if (strcasecmp(keywords[*cpt], "mode") == 0)
		{
			if(!keywords[++*cpt])
				return 1;

			if (strcasecmp(keywords[*cpt], "bridged") == 0)
				*mode = CMMD_MC6_MODE_BRIDGED;
			else if (strcasecmp(keywords[*cpt], "routed") == 0)
				*mode = CMMD_MC6_MODE_ROUTED;
			else 
				return 1;

		}
		else if (strcasecmp(keywords[*cpt], "queue") == 0)
		{

			if(!keywords[++*cpt])
				return 1;

			/*Get an integer from the string*/
			endptr = NULL;
			tmp = strtoul(keywords[*cpt], &endptr, 0);
			listener->q_bit = 1;

			if (tmp < FPP_NUM_QUEUES)
				listener->queue = tmp;
			else 
				return 1;
		}
		else if (strcasecmp(keywords[*cpt], "shapers") == 0)
		{
			if(!keywords[++*cpt])
				return 1;

			/*Get an integer from the string*/
			endptr = NULL;
			tmp = strtoul(keywords[*cpt], &endptr, 0);

			if (tmp <= 0xFF)
				listener->shaper_mask = tmp;
			else 
				return 1;
		}
		else if(strcasecmp(keywords[*cpt],"if") == 0 )
		{
			if(action != CMMD_MC_ACTION_UPDATE)
				return 1;

			if(!keywords[++*cpt])
				return 1;

			if (strlen(keywords[*cpt]) > 10) {
				cmm_print(DEBUG_STDERR, "Error : interface name %s limited to 10 characters\n", keywords[*cpt]);
				return 1;
			}
			strcpy(listener->new_output_device_str, keywords[*cpt]);
			listener->Ifbit = 1;	
		}
		else
			return 1;
		++*cpt;

	}
	return 0;
}


/************************************************************
 *
 *
 *
 ************************************************************/
int cmmMc6SetProcess(char ** keywords, int tabStart, daemon_handle_t daemon_handle)
{
	int cpt = tabStart;
	unsigned int tmp;
	char * endptr;
	int rc = 0;
	char sndBuffer[256];
	char rcvBuffer[256];
	char interfaceName[11] = {};
	cmmd_mc6_entry_t * entryCmd = (cmmd_mc6_entry_t *) sndBuffer;
	cmmd_mc6_listener_t * listener = (cmmd_mc6_listener_t *) (sndBuffer + sizeof(cmmd_mc6_entry_t));
	int listenerCnt = 0;
	u_int8_t mode = 0;

	memset(sndBuffer, 0, sizeof(sndBuffer));
	listener->timer = 0xFFFFFFFF;
	listener->q_bit = 0;
	listener->uc_bit = 0; // Multicast by default when a new entry is added
	listener->Ifbit = 0;

	if(!keywords[cpt])
		goto help;

	if(strcasecmp(keywords[cpt], "interface") == 0)
	{
		if(!keywords[++cpt])
			goto help;

		if (strlen(keywords[cpt]) > 10) {
			cmm_print(DEBUG_STDERR, "Error : interface name %s limited to 10 characters\n", keywords[cpt]);
			goto help;
		}
		strcpy(interfaceName, keywords[cpt]);
		strcpy(listener->output_device_str,interfaceName);
	}
	else if(strcasecmp(keywords[cpt], "reset") == 0)
	{
		/*Reset, special case*/
		if(cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_RESET, NULL, 0, rcvBuffer) == 2)
		{
			if ( ((unsigned short *)rcvBuffer)[0] != 0)
				cmm_print(DEBUG_STDERR, "Error %d received from FPP for CMD_MC6_RESET\n", ((unsigned short *)rcvBuffer)[0]);
		}
		return ((unsigned short *)rcvBuffer)[0];
	}
	else if (strcasecmp(keywords[cpt], "mode") == 0)
	{
		unsigned short mc6_mode;

		if (!keywords[++cpt])
			goto help;

		if (strcasecmp(keywords[cpt], "bridge") == 0)
			mc6_mode = CMMD_MC6_MODE_BRIDGED;
		else if (strcasecmp(keywords[cpt], "route") == 0)
			mc6_mode = CMMD_MC6_MODE_ROUTED;
		else
			goto help;

		if(cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_MODE, &mc6_mode, sizeof(mc6_mode), rcvBuffer) == 2)
		{
			if ( ((unsigned short *)rcvBuffer)[0] != 0)
				cmm_print(DEBUG_STDERR, "Error %d received from FPP for CMD_MC6_MODE\n", ((unsigned short *)rcvBuffer)[0]);
		}
		return ((unsigned short *)rcvBuffer)[0];

	}
	else
		goto keyword_error;

	if(!keywords[++cpt])
		goto help;
	
	if(strcasecmp(keywords[cpt], "add") == 0)
	{		
		entryCmd->action = CMMD_MC_ACTION_ADD;
	}
	else if(strcasecmp(keywords[cpt], "del") == 0)
	{
		entryCmd->action = CMMD_MC_ACTION_REMOVE;
	}
	else if(strcasecmp(keywords[cpt], "update") == 0)
	{
		entryCmd->action = CMMD_MC_ACTION_UPDATE;
	}
	else
		goto keyword_error;

	if(!keywords[++cpt])
		goto help;

	if (strcasecmp(keywords[cpt], "group") == 0)
	{
		if(!keywords[++cpt])
			goto help;

		/*Get an integer from the string for the MASK*/
		endptr = NULL;
		tmp = strtoul(keywords[cpt], &endptr, 0);
		entryCmd->src_mask_len = tmp;

		if(!keywords[++cpt])
			goto help;

		/*Get an integer from the string for the IPsrc*/
		if(inet_pton(AF_INET6, keywords[cpt], &entryCmd->src_addr) != 1)
			goto help;

		if(!keywords[++cpt])
			goto help;

		/*Get an integer from the string for the IPdst*/
		if(inet_pton(AF_INET6, keywords[cpt], &entryCmd->dst_addr) != 1)
			goto help;

		if (! (entryCmd->dst_addr[0] & 0xFF))
			goto help;
	}

	++cpt;

	while(keywords[cpt])
	{
		strcpy(((cmmd_mc6_listener_t *)listener + listenerCnt)->output_device_str,interfaceName);
		if (strncasecmp(keywords[cpt], "listener",strlen(keywords[cpt])) == 0) //May be a case of multiple listeners, parse differently
		{
			++cpt;
			if(!cmmMcParseListener(keywords, &cpt, listener + listenerCnt, &mode, entryCmd->action))
			{
				if(++listenerCnt ==  MC6_MAX_LISTENERS_IN_QUERY)
					//Send first batch to FPP and reset listener count
				{

					entryCmd->num_output = listenerCnt;
					if(cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_MULTICAST, sndBuffer, sizeof(cmmd_mc6_entry_t) + (listenerCnt * sizeof(cmmd_mc6_listener_t)), rcvBuffer) == 2)
					{
						if ( (rc = ((unsigned short *)rcvBuffer)[0]) != 0)
						{
							if(rc == CMMD_ERR_NOT_CONFIGURED)
								cmm_print(DEBUG_STDERR, "%d Interface not yet up in FPP, will be configured when interface comes up\n", rc);
							else if(rc == CMMD_ERR_MC_MAX_LISTENERS)
								cmm_print(DEBUG_STDERR, "Error %d MAX listeners for the group exhausted\n", rc);
							else if(rc == CMMD_ERR_MC_INTERFACE_NOT_ALLOWED)
								cmm_print(DEBUG_STDERR, "Error %d Interface configured cannot support Unicast MAC\n", rc);
							else if(rc == CMMD_ERR_MC_ENTRY_OVERLAP)
							{
								cmm_print(DEBUG_STDERR, "Error %d Overlapping entry configured\n", rc);
								entryCmd->action = CMMD_MC_ACTION_REMOVE_LOCAL;
								cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_MULTICAST, sndBuffer, 
								sizeof(cmmd_mc6_entry_t) + (listenerCnt * sizeof(cmmd_mc6_listener_t)), rcvBuffer);	
							}
							else
								cmm_print(DEBUG_STDERR, "Error %d received from FPP for CMD_MC6_MULTICAST\n", rc);
						}
					}
					listenerCnt = 0;
					memset(sndBuffer + sizeof(cmmd_mc6_entry_t), 0 , sizeof(sndBuffer) - sizeof(cmmd_mc6_entry_t));
				}
			}
			else
				goto help;
		}
		else
		{
			if(!cmmMcParseListener(keywords, &cpt, listener, &mode, entryCmd->action))
			{
				listener->q_bit = 0; // Default config listener q_bit is always zero.
				entryCmd->queue = listener->queue;
				entryCmd->mode = mode;
			}
			else
				goto help;
		}

	}
	if(!listenerCnt & !entryCmd->num_output)
		listenerCnt = 1; //fall back to legacy design, single listener is configured.

	entryCmd->num_output = listenerCnt;

	if(listenerCnt && (cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_MULTICAST, sndBuffer, sizeof(cmmd_mc6_entry_t) + (listenerCnt * sizeof(cmmd_mc6_listener_t)), rcvBuffer) == 2))
	{
		if ( (rc = ((unsigned short *)rcvBuffer)[0]) != 0)
		{
			if(rc == CMMD_ERR_NOT_CONFIGURED)
				cmm_print(DEBUG_STDERR, "%d Interface not yet up in FPP, will be configured when interface comes up\n", rc);
			else if(rc == CMMD_ERR_MC_MAX_LISTENERS)
				cmm_print(DEBUG_STDERR, "Error %d MAX listeners for the group exhausted\n", rc);
			else if(rc == CMMD_ERR_MC_INTERFACE_NOT_ALLOWED)
				cmm_print(DEBUG_STDERR, "Error %d Interface configured cannot support Unicast MAC\n", rc);
			else if(rc == CMMD_ERR_MC_ENTRY_OVERLAP)
			{
				cmm_print(DEBUG_STDERR, "Error %d Overlapping entry configured\n", rc);
				entryCmd->action = CMMD_MC_ACTION_REMOVE_LOCAL;
				cmmSendToDaemon(daemon_handle, CMMD_CMD_MC6_MULTICAST, sndBuffer, 
				sizeof(cmmd_mc6_entry_t) + (listenerCnt * sizeof(cmmd_mc6_listener_t)), rcvBuffer);	
			}
			else
				cmm_print(DEBUG_STDERR, "Error %d received from FPP for CMD_MC6_MULTICAST\n", rc);
		}
	}
	return rc;

keyword_error:
	cmm_print(DEBUG_STDERR, "ERROR: Unknown keyword %s\n", keywords[cpt]);

help:
	cmmMc6SetPrintHelp();
	return -1;
}


/************************************************************
 * cmmMc6ProcessClientCmd
 *    This function do needed local process before sending
 *    the command to FPP
 *     
 ************************************************************/

int cmmMc6ProcessClientCmd(FCI_CLIENT* fci_handle, int function_code, u_int8_t *cmd_buf, u_int16_t cmd_len, u_int16_t *res_buf, u_int16_t *res_len)
{
	int ret = 0;
	cmmd_mc6_entry_t * entry = (cmmd_mc6_entry_t *) cmd_buf;
	cmmd_mc6_listener_t * listener;

	switch(function_code)
	{
		case CMMD_CMD_MC6_MULTICAST:
			// We need to check if we don't have to do something with the interface names

			//Sanity checks
			if (cmd_len < sizeof(cmmd_mc6_entry_t))
			{
				res_buf[0] = CMMD_ERR_WRONG_COMMAND_SIZE;
				break;
			}

			if ((entry->action == CMMD_ACTION_QUERY) ||
                            (entry->action == CMMD_ACTION_QUERY_CONT))
                             goto FCI_CMD;

			if (entry->num_output > MC6_MAX_LISTENERS_IN_QUERY)
			{
				res_buf[0] = CMMD_ERR_WRONG_COMMAND_PARAM; 
				break;
			}

			if (cmd_len < (sizeof(cmmd_mc6_entry_t) + (entry->num_output * sizeof(cmmd_mc6_listener_t))))
			{
				res_buf[0] = CMMD_ERR_WRONG_COMMAND_SIZE;
				break;
			}


			// Check if the listeners are on virtual interface
			listener = (cmmd_mc6_listener_t *)(cmd_buf + sizeof(cmmd_mc6_entry_t) );
			switch( entry->action )
			{
				case CMMD_MC_ACTION_ADD:
				case CMMD_MC_ACTION_REMOVE:
				case CMMD_MC_ACTION_UPDATE:
					res_buf[0] = CMMD_ERR_OK;
					ret = mc6_update_entry(entry, listener, entry->action );
					if( ret != CMMD_ERR_OK )
					{
						res_buf[0] = ret;
						goto out;
					}
					goto FCI_CMD;		
					break;
				case CMMD_MC_ACTION_REMOVE_LOCAL:
					mc_remove_group(entry,AF_INET6);
					break;
					
			}
out:
			
			break;

		case CMMD_CMD_MC6_RESET:
			__pthread_mutex_lock(&itf_table.lock);
			__pthread_mutex_lock(&ctMutex);
			__pthread_mutex_lock(&rtMutex);
			__pthread_mutex_lock(&neighMutex);
			__pthread_mutex_lock(&flowMutex);
			__pthread_mutex_lock(&mc_lock);
			
			res_buf[0] = fci_write(fci_handle, CMMD_CMD_MC6_RESET, 0, NULL);
			if ( ret == CMMD_ERR_OK )
				mc_reset(AF_INET);		

			__pthread_mutex_unlock(&mc_lock);
			__pthread_mutex_unlock(&flowMutex);
			__pthread_mutex_unlock(&neighMutex);
			__pthread_mutex_unlock(&rtMutex);
			__pthread_mutex_unlock(&ctMutex);
			__pthread_mutex_unlock(&itf_table.lock);
			break;

		case CMMD_CMD_MC6_MODE:
			goto FCI_CMD;

		default:
			res_buf[0] = CMMD_ERR_UNKNOWN_COMMAND;
			break;
	}

	*res_len = 2;
	return 0;

FCI_CMD:
	return fci_cmd(fci_handle, function_code, (u_int16_t*)cmd_buf, cmd_len, res_buf, res_len);
}

