791 lines
26 KiB
C
791 lines
26 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcpc6_shell.c,v $ $Revision: 1.13.18.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipdhcpc6/src/ipdhcpc6_shell.c,v $
|
|
* $Author: ulf $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipdhcpc6_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_sock6.h>
|
|
#include <ipcom_list.h>
|
|
#include <ipcom_hash.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_tmo2.h>
|
|
|
|
#include "ipdhcpc6.h"
|
|
#include "ipdhcpc6_h.h"
|
|
#include "ipdhcpc6_msg.h"
|
|
#include "ipdhcpc6_if.h"
|
|
#include "ipdhcpc6_ia.h"
|
|
#include "ipdhcpc6_shell.h"
|
|
#include "ipdhcpc6_attr.h"
|
|
#include "ipdhcpc6_rtadv.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipdhcpc6_shell_args
|
|
{
|
|
Ipdhcpc6_context_t *context;
|
|
Ipdhcpc6_tagcomm_buffer_t *buf;
|
|
Ipdhcpc6_if_t *ifp;
|
|
Ipdhcpc6_ia_t *ia;
|
|
Ip_u32 cmd;
|
|
} Ipdhcpc6_shell_args_t;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
IP_STATIC int ipdhcpc6_shell_parse_ia_command(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag);
|
|
IP_STATIC int ipdhcpc6_shell_parse_ia_command_attributes(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag);
|
|
IP_STATIC int ipdhcpc6_shell_parse_ia_ifobj_attributes(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
static Ipdhcpc6_tagcomm_parser_t ipdhcpc6_shell_commands[] =
|
|
{
|
|
{
|
|
IPDHCPC6_CMD_IA_INFO,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{
|
|
IPDHCPC6_CMD_IA_REFRESH,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{
|
|
IPDHCPC6_CMD_IA_RELEASE,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{
|
|
IPDHCPC6_CMD_IA_HISTORY_FLUSH,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{
|
|
IPDHCPC6_CMD_IA_RTSOL,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{
|
|
IPDHCPC6_CMD_IA_BOUND_ADD,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{
|
|
IPDHCPC6_CMD_IA_BOUND_DEL,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command
|
|
},
|
|
|
|
{ 0, IP_NULL }
|
|
};
|
|
|
|
|
|
static Ipdhcpc6_tagcomm_parser_t ipdhcpc6_shell_ia_command_attributes[] =
|
|
{
|
|
{
|
|
IPDHCPC6_IA_OBJECT_IF,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command_attributes
|
|
},
|
|
{
|
|
IPDHCPC6_IA_IDENT_DUID,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_command_attributes
|
|
},
|
|
{ 0, IP_NULL }
|
|
};
|
|
|
|
static Ipdhcpc6_tagcomm_parser_t ipdhcpc6_shell_ia_ifobj_attributes[] =
|
|
{
|
|
{
|
|
IPDHCPC6_IA_OBJECT_IF_AUTOMATIC,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_ifobj_attributes
|
|
},
|
|
{
|
|
IPDHCPC6_IA_OBJECT_IF_CONFIG,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_ifobj_attributes
|
|
},
|
|
{
|
|
IPDHCPC6_IA_OBJECT_IA,
|
|
(Ipdhcpc6_tagcomm_parse_object_t) ipdhcpc6_shell_parse_ia_ifobj_attributes
|
|
},
|
|
|
|
{ 0, IP_NULL }
|
|
};
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_context_client_free
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipdhcpc6_shell_context_client_free(Ipdhcpc6_shell_client_t *cfd)
|
|
{
|
|
ipcom_list_remove(&cfd->next);
|
|
|
|
ipdhcpc6_util_free(&cfd->rbuf.buffer);
|
|
if (cfd->fd != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(cfd->fd);
|
|
ipdhcpc6_util_free(&cfd);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_parse_errout
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_shell_parse_errout(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag)
|
|
{
|
|
ipdhcpc6_tagcomm_failure(args->buf,
|
|
tag,
|
|
IPDHCPC6_TAGCOMM_STATUS_UNKNOWN_TAG);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_parse_ia_ifobj_attributes
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_shell_parse_ia_ifobj_attributes(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag)
|
|
{
|
|
Ipdhcpc6_attr_ia_t *iaobj;
|
|
|
|
switch (tag->tag)
|
|
{
|
|
case IPDHCPC6_IA_OBJECT_IF_CONFIG:
|
|
if (args->cmd == IPDHCPC6_CMD_IA_INFO)
|
|
{
|
|
ipdhcpc6_tagcomm_enter_tag(args->buf,
|
|
IPDHCPC6_IA_OBJECT_IF_CONFIG,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK);
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_RAPID_COMMIT,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.rapid_commit,
|
|
sizeof(args->ifp->conf.rapid_commit));
|
|
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_INFO_ONLY,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.information_only,
|
|
sizeof(args->ifp->conf.information_only));
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_DNS,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.dns,
|
|
sizeof(args->ifp->conf.dns));
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_SNTP,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.sntp,
|
|
sizeof(args->ifp->conf.sntp));
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_INFO_REFRESH,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.information_only,
|
|
sizeof(args->ifp->conf.information_only));
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_SIP,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.sip,
|
|
sizeof(args->ifp->conf.sip));
|
|
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_CONFIG_FQDN,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->conf.fqdn.fqdn,
|
|
sizeof(args->ifp->conf.fqdn.fqdn));
|
|
ipdhcpc6_tagcomm_leave_tag(args->buf);
|
|
}
|
|
break;
|
|
case IPDHCPC6_IA_OBJECT_IF_AUTOMATIC:
|
|
if (args->cmd == IPDHCPC6_CMD_IA_INFO)
|
|
{
|
|
if (args->ifp->mode == IPDHCPC6_MODE_AUTOMATIC)
|
|
{
|
|
ipdhcpc6_tagcomm_enter_tag(args->buf,
|
|
IPDHCPC6_IA_OBJECT_IF_AUTOMATIC,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK);
|
|
if (IP_IN6_ARE_ADDR_EQUAL(&args->ifp->automatic.rtr, &ip_in6addr_any) == IP_FALSE)
|
|
{
|
|
ipdhcpc6_tagcomm_enter_tag(args->buf,
|
|
IPDHCPC6_IA_OBJECT_SERVER,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK);
|
|
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_ADDRESS,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->automatic.rtr,
|
|
sizeof(args->ifp->automatic.rtr));
|
|
|
|
|
|
ipdhcpc6_tagcomm_leave_tag(args->buf);
|
|
}
|
|
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_AUTOMATIC_MANAGED,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->automatic.runtime.managed,
|
|
sizeof(args->ifp->automatic.runtime.managed));
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_ATTR_IF_AUTOMATIC_OTHER,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
&args->ifp->automatic.runtime.other,
|
|
sizeof(args->ifp->automatic.runtime.other));
|
|
ipdhcpc6_tagcomm_leave_tag(args->buf);
|
|
}
|
|
}
|
|
break;
|
|
case IPDHCPC6_IA_OBJECT_IA:
|
|
iaobj = ipdhcpc6_attr_ia_parse(tag, IPDHCPC6_TAGCOMM_TAG_IDENTITY);
|
|
if (iaobj)
|
|
{
|
|
if (iaobj->iatype >= IPDHCPC6_IA_TYPE_MAX)
|
|
{
|
|
ipdhcpc6_tagcomm_failure(args->buf,
|
|
tag,
|
|
IPDHCPC6_ATTR_TAG_STATUS_UNKNOWN_IA);
|
|
}
|
|
else
|
|
{
|
|
/* Not specified */
|
|
if (iaobj->ianame == IP_NULL && iaobj->iaid == 0)
|
|
{
|
|
args->ia = IPCOM_LIST_FIRST(&args->ifp->ia_head[iaobj->iatype]);
|
|
while (args->ia != IP_NULL)
|
|
{
|
|
args->ia->table->attributes(args->cmd,
|
|
args->ia,
|
|
tag,
|
|
args->buf);
|
|
|
|
/* Next IA */
|
|
args->ia = IPCOM_LIST_NEXT(&args->ia->next);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
args->ia = ipdhcpc6_ia_lookup_by_iaobj(args->ifp, iaobj);
|
|
if (args->ia == IP_NULL)
|
|
{
|
|
ipdhcpc6_tagcomm_failure(args->buf,
|
|
tag,
|
|
IPDHCPC6_ATTR_TAG_STATUS_UNKNOWN_IA);
|
|
}
|
|
else
|
|
{
|
|
args->ia->table->attributes(args->cmd,
|
|
args->ia,
|
|
tag,
|
|
args->buf);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ipdhcpc6_attr_ia_free(&iaobj);
|
|
}
|
|
else
|
|
{
|
|
ipdhcpc6_tagcomm_failure(args->buf,
|
|
tag,
|
|
IPDHCPC6_TAGCOMM_STATUS_PARSE_FAILED);
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_parse_ia_command_attributes
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_shell_parse_ia_command_attributes(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag)
|
|
{
|
|
int result = 0;
|
|
Ipdhcpc6_attr_if_t *ifobj;
|
|
|
|
/* Store base command */
|
|
switch (tag->tag)
|
|
{
|
|
case IPDHCPC6_IA_OBJECT_IF:
|
|
|
|
ifobj = ipdhcpc6_attr_if_parse(tag, IPDHCPC6_TAGCOMM_TAG_IDENTITY);
|
|
if (ifobj)
|
|
{
|
|
if (ifobj->ifname == IP_NULL)
|
|
{
|
|
/* Wild card match */
|
|
args->ifp = IPCOM_LIST_FIRST(&args->context->ifctx->ifp_head);
|
|
while (args->ifp != IP_NULL)
|
|
{
|
|
ipdhcpc6_tagcomm_enter_tag(args->buf, tag->tag, IPDHCPC6_TAGCOMM_STATUS_OK);
|
|
ipdhcpc6_if_attr_header(args->ifp, args->buf);
|
|
|
|
switch (args->cmd)
|
|
{
|
|
case IPDHCPC6_CMD_IA_RTSOL:
|
|
ipdhcpc6_rtadv_up(args->ifp->context->context, args->ifp);
|
|
break;
|
|
default:
|
|
result = ipdhcpc6_tagcomm_parse(ipdhcpc6_shell_ia_ifobj_attributes,
|
|
(Ipdhcpc6_tagcomm_parse_object_t)ipdhcpc6_shell_parse_errout,
|
|
tag,
|
|
args);
|
|
break;
|
|
}
|
|
|
|
|
|
ipdhcpc6_tagcomm_leave_tag(args->buf);
|
|
|
|
if (result != 0)
|
|
break;
|
|
|
|
/* Next interface */
|
|
args->ifp = IPCOM_LIST_NEXT(&args->ifp->next);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
args->ifp = ipdhcpc6_if_lookup_by_ifobj(args->context, ifobj);
|
|
if (args->ifp == IP_NULL)
|
|
{
|
|
ipdhcpc6_tagcomm_failure(args->buf,
|
|
tag,
|
|
IPDHCPC6_ATTR_TAG_STATUS_UNKNOWN_INTERFACE);
|
|
}
|
|
else
|
|
{
|
|
ipdhcpc6_tagcomm_enter_tag(args->buf, tag->tag, IPDHCPC6_TAGCOMM_STATUS_OK);
|
|
ipdhcpc6_if_attr_header(args->ifp, args->buf);
|
|
|
|
switch (args->cmd)
|
|
{
|
|
case IPDHCPC6_CMD_IA_RTSOL:
|
|
ipdhcpc6_rtadv_up(args->ifp->context->context, args->ifp);
|
|
break;
|
|
default:
|
|
result = ipdhcpc6_tagcomm_parse(ipdhcpc6_shell_ia_ifobj_attributes,
|
|
(Ipdhcpc6_tagcomm_parse_object_t)ipdhcpc6_shell_parse_errout,
|
|
tag,
|
|
args);
|
|
break;
|
|
}
|
|
|
|
ipdhcpc6_tagcomm_leave_tag(args->buf);
|
|
}
|
|
|
|
}
|
|
|
|
ipdhcpc6_attr_if_free(&ifobj);
|
|
}
|
|
else
|
|
{
|
|
ipdhcpc6_tagcomm_failure(args->buf,
|
|
tag,
|
|
IPDHCPC6_TAGCOMM_STATUS_PARSE_FAILED);
|
|
}
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_parse_ia_command
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_shell_parse_ia_command(Ipdhcpc6_shell_args_t *args,
|
|
Ipdhcpc6_tagcomm_tag_t *tag)
|
|
{
|
|
int result;
|
|
|
|
/* Store base command */
|
|
args->cmd = tag->tag;
|
|
|
|
ipdhcpc6_tagcomm_enter_tag(args->buf, tag->tag, IPDHCPC6_TAGCOMM_STATUS_OK);
|
|
|
|
/* Add the DUID */
|
|
ipdhcpc6_tagcomm_add_tag(args->buf,
|
|
IPDHCPC6_IA_IDENT_DUID,
|
|
IPDHCPC6_TAGCOMM_STATUS_OK,
|
|
args->context->ifctx->duid.head,
|
|
args->context->ifctx->duid.offset);
|
|
|
|
result = ipdhcpc6_tagcomm_parse(ipdhcpc6_shell_ia_command_attributes,
|
|
(Ipdhcpc6_tagcomm_parse_object_t)ipdhcpc6_shell_parse_errout,
|
|
tag,
|
|
args);
|
|
|
|
|
|
ipdhcpc6_tagcomm_leave_tag(args->buf);
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_command
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipdhcpc6_shell_parse_command(Ipdhcpc6_context_t *context,
|
|
Ipdhcpc6_tagcomm_tag_t *tag,
|
|
Ipdhcpc6_tagcomm_buffer_t *response)
|
|
{
|
|
Ipdhcpc6_shell_args_t args;
|
|
|
|
ipcom_memset(&args, 0, sizeof(args));
|
|
|
|
args.context = context;
|
|
args.buf = response;
|
|
|
|
return ipdhcpc6_tagcomm_parse(ipdhcpc6_shell_commands,
|
|
(Ipdhcpc6_tagcomm_parse_object_t)ipdhcpc6_shell_parse_errout,
|
|
tag,
|
|
&args);
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_context_alloc
|
|
*===========================================================================
|
|
* Description: Allocate an shell context
|
|
* Parameters: context - The DHCPC6 context.
|
|
* Returns: An shell context.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipdhcpc6_shell_context_t *
|
|
ipdhcpc6_shell_context_alloc(struct Ipdhcpc6_context *context)
|
|
{
|
|
Ipdhcpc6_shell_context_t *shellctx = ipcom_calloc(1, sizeof(*shellctx));
|
|
if (shellctx)
|
|
{
|
|
struct Ip_sockaddr_in6 sin6;
|
|
int opt;
|
|
|
|
shellctx->context = context;
|
|
|
|
/* Create the client head */
|
|
ipcom_list_init(&shellctx->head);
|
|
|
|
/* Create the FD */
|
|
shellctx->client_fd = ipcom_socket(IP_AF_INET6, IP_SOCK_STREAM, IP_IPPROTO_TCP);
|
|
if (shellctx->client_fd == IP_INVALID_SOCKET)
|
|
goto errout;
|
|
|
|
ipcom_memset(&sin6, 0, sizeof(sin6));
|
|
sin6.sin6_family = IP_AF_INET6;
|
|
sin6.sin6_len = sizeof(sin6);
|
|
sin6.sin6_port = ip_htons(IPDHCPC6_CLIENT_PORT);
|
|
sin6.sin6_addr = ip_in6addr_loopback;
|
|
|
|
opt = 1;
|
|
if (ipcom_setsockopt(shellctx->client_fd, IP_SOL_SOCKET, IP_SO_REUSEPORT, (char *)&opt, sizeof(opt)) < 0)
|
|
{
|
|
IPCOM_LOG2(WARNING,
|
|
"%s: Failed to set reuse port on client socket, errno = %d", context->name, ipcom_errno);
|
|
}
|
|
|
|
if (ipcom_bind(shellctx->client_fd, (struct Ip_sockaddr *) &sin6, sizeof(sin6)) < 0)
|
|
{
|
|
IPCOM_LOG2(ERR,
|
|
"%s: Failed to bind client socket, errno = %d", context->name, ipcom_errno);
|
|
goto errout;
|
|
}
|
|
|
|
if (ipcom_listen(shellctx->client_fd, 5) < 0)
|
|
{
|
|
IPCOM_LOG2(ERR,
|
|
"%s: Failed to listen on client socket, errno = %d", context->name, ipcom_errno);
|
|
goto errout;
|
|
}
|
|
}
|
|
|
|
return shellctx;
|
|
|
|
errout:
|
|
if (shellctx->client_fd != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(shellctx->client_fd);
|
|
ipdhcpc6_util_free(&shellctx);
|
|
return IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_context_free
|
|
*===========================================================================
|
|
* Description: Free an shell context
|
|
* Parameters: shellctxp - Pointer to the DHCPC6 shellcontext.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_shell_context_free(Ipdhcpc6_shell_context_t **shellctxp)
|
|
{
|
|
Ipdhcpc6_shell_context_t *shellctx = *shellctxp;
|
|
if (shellctx)
|
|
{
|
|
Ipdhcpc6_shell_client_t *cfd;
|
|
while ((cfd = IPCOM_LIST_FIRST(&shellctx->head)) != IP_NULL)
|
|
ipdhcpc6_shell_context_client_free(cfd);
|
|
|
|
ipcom_socketclose(shellctx->client_fd);
|
|
ipdhcpc6_util_free(&shellctx);
|
|
}
|
|
|
|
*shellctxp = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_context_fdset_init
|
|
*===========================================================================
|
|
* Description: Initialize all file descriptors of this context
|
|
* Parameters: shellctx - Attribute context
|
|
* rset - Read set to initialize.
|
|
* mfd - Maximum file descriptor.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_shell_context_fdset_init(Ipdhcpc6_shell_context_t *shellctx,
|
|
Ip_fd_set *rset,
|
|
int *mfd)
|
|
{
|
|
int maxfd = *mfd;
|
|
Ipdhcpc6_shell_client_t *cfd;
|
|
|
|
/* Add the client socket */
|
|
IP_FD_SET(shellctx->client_fd, rset);
|
|
maxfd = IP_MAX(shellctx->client_fd, maxfd);
|
|
|
|
cfd = IPCOM_LIST_FIRST(&shellctx->head);
|
|
while (cfd != IP_NULL)
|
|
{
|
|
IP_FD_SET(cfd->fd, rset);
|
|
maxfd = IP_MAX(cfd->fd, maxfd);
|
|
cfd = IPCOM_LIST_NEXT(&cfd->next);
|
|
}
|
|
|
|
*mfd = maxfd;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_shell_context_fdset_process
|
|
*===========================================================================
|
|
* Description: Process all file descriptors of this context
|
|
* Parameters: shellctx - Attribute context
|
|
* rset - Read set to initialize.
|
|
* status - Incoming status
|
|
* Returns: Outgoing status
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipdhcpc6_shell_context_fdset_process(Ipdhcpc6_shell_context_t *shellctx,
|
|
Ip_fd_set *rset,
|
|
int status)
|
|
{
|
|
Ipdhcpc6_shell_client_t *cfd, *ncfd;
|
|
/* Check the clients */
|
|
|
|
cfd = IPCOM_LIST_FIRST(&shellctx->head);
|
|
while (cfd != IP_NULL)
|
|
{
|
|
Ip_ssize_t ret;
|
|
ncfd = IPCOM_LIST_NEXT(&cfd->next);
|
|
|
|
/**/
|
|
if (IP_FD_ISSET(cfd->fd, rset))
|
|
{
|
|
if (cfd->rbuf.buffer == IP_NULL)
|
|
{
|
|
if (ipdhcpc6_attr_recvhdr(cfd->fd, &cfd->rbuf) == IP_FALSE)
|
|
{
|
|
ipdhcpc6_shell_context_client_free(cfd);
|
|
cfd = IP_NULL;
|
|
}
|
|
}
|
|
|
|
if (cfd)
|
|
{
|
|
ret = ipdhcpc6_attr_read(cfd->fd, &cfd->rbuf, IP_FALSE);
|
|
if (ret < 0)
|
|
ipdhcpc6_shell_context_client_free(cfd);
|
|
else if (ret == 0)
|
|
{
|
|
Ipdhcpc6_tagcomm_buffer_t *response = ipdhcpc6_tagcomm_buffer_alloc();
|
|
|
|
if (response)
|
|
{
|
|
/* We've got an entire command */
|
|
if (ipdhcpc6_shell_parse_command(shellctx->context,
|
|
(void *)cfd->rbuf.buffer,
|
|
response) == 0)
|
|
{
|
|
ipdhcpc6_attr_sendmsg(cfd->fd, response);
|
|
}
|
|
|
|
ipdhcpc6_tagcomm_buffer_free(&response);
|
|
}
|
|
|
|
/* Free the current buffer */
|
|
ipdhcpc6_util_free(&cfd->rbuf.buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Do next */
|
|
cfd = ncfd;
|
|
}
|
|
|
|
/* Check the */
|
|
if (IP_FD_ISSET(shellctx->client_fd, rset))
|
|
{
|
|
/* Do create a new client */
|
|
ncfd = ipcom_calloc(1, sizeof(*ncfd));
|
|
if (ncfd)
|
|
{
|
|
struct Ip_sockaddr_in6 sin6;
|
|
Ip_socklen_t slen = sizeof(sin6);
|
|
|
|
ipcom_list_insert_last(&shellctx->head, &ncfd->next);
|
|
ncfd->fd = ipcom_accept(shellctx->client_fd, (struct Ip_sockaddr *)&sin6, &slen);
|
|
|
|
if (ncfd->fd == IP_INVALID_SOCKET)
|
|
ipdhcpc6_shell_context_client_free(ncfd);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|