462 lines
15 KiB
C
462 lines
15 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipdhcpc6_rtsock.c,v $ $Revision: 1.4.56.2 $
|
|
* $Source: /home/interpeak/CVSRoot/ipdhcpc6/src/ipdhcpc6_rtsock.c,v $
|
|
* $Author: svc-cmnet $
|
|
* $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 <ipnet.h>
|
|
#include <ipnet_ctrl.h>
|
|
#include <ipcom_netlink.h>
|
|
|
|
#include "ipdhcpc6.h"
|
|
#include "ipdhcpc6_h.h"
|
|
#include "ipdhcpc6_msg.h"
|
|
#include "ipdhcpc6_if.h"
|
|
#include "ipdhcpc6_ia.h"
|
|
#include "ipdhcpc6_sock.h"
|
|
#include "ipdhcpc6_rtsock.h"
|
|
#include "ipdhcpc6_rtadv.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_nlsock_process
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipdhcpc6_nlsock_process(Ipdhcpc6_rtsock_context_t *rtctx, int vr_index)
|
|
{
|
|
Ip_ssize_t length;
|
|
|
|
/* Read routing messages */
|
|
length = ipcom_recv(rtctx->nl_fd[vr_index],
|
|
rtctx->buffer,
|
|
sizeof(rtctx->buffer),
|
|
0);
|
|
if (length > 0)
|
|
{
|
|
Ipdhcpc6_rtadv_context_t *rtadvctx = rtctx->context->rtadvctx;
|
|
Ipdhcpc6_sock_context_t *sctx = rtctx->context->sctx;
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)rtctx->buffer;
|
|
|
|
/* Parse the messages */
|
|
while (IP_NLMSG_OK(nlh, (unsigned)length))
|
|
{
|
|
switch (nlh->nlmsg_type)
|
|
{
|
|
/* we must listen this event due to if the vr delete and we has
|
|
* DHCPC6 entity on that vr, the DHCP6 entity will not have a
|
|
* chance to restart when the deleted vr re-created */
|
|
case IP_RTM_NEWLINK:
|
|
case IP_RTM_DELLINK:
|
|
{
|
|
char ifname[IP_IFNAMSIZ + 1];
|
|
struct Ip_ifinfomsg *ifm;
|
|
Ipdhcpc6_if_t *ifp;
|
|
|
|
/* re-create the send/receive socket */
|
|
ipdhcpc6_sock_create(sctx, vr_index);
|
|
ipdhcpc6_rtadv_sock_create(rtadvctx, vr_index);
|
|
|
|
ifm = (struct Ip_ifinfomsg *)IP_NLMSG_DATA(nlh);
|
|
ip_assert(IP_NULL != ifm);
|
|
|
|
if (ipdhcpc6_if_indextoname(ifm->ifi_index, ifname, vr_index))
|
|
{
|
|
ifp = ipdhcpc6_if_lookup_by_name(rtctx->context, ifname);
|
|
if (ifp)
|
|
{
|
|
IPCOM_LOG4(INFO,
|
|
"%s: received %d for interface [%d,%s]",
|
|
rtctx->context->name,
|
|
nlh->nlmsg_type,
|
|
vr_index,
|
|
ifname);
|
|
|
|
ipdhcpc6_if_update_state(ifp);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* XXX
|
|
* 1, this VR socket will exist in system, because the NEWVR event
|
|
* can ONLY be received on this vr NL socket, .
|
|
* 2, there is no chance for us to get the VR changed event(no
|
|
* this kind of event), SO for the following scenario, do nothing :
|
|
* ifconfig simnet1 vr 1 -- first in VR 1 and begin DHCPC6 process
|
|
* ifconfig simnet1 vr 0 -- change this interface to 0 */
|
|
case IP_RTM_DELVR:
|
|
{
|
|
/*struct Ip_vrmsg *ipvr = (struct Ip_vrmsg *)IP_NLMSG_DATA(nlh);*/
|
|
|
|
/* close the send/receive socket */
|
|
if (sctx->udp_fd[vr_index] != IP_INVALID_SOCKET)
|
|
{
|
|
int ret = ipcom_socketclose(sctx->udp_fd[vr_index]);
|
|
if (ret < 0)
|
|
{
|
|
IPCOM_LOG3(ERR,
|
|
"close socket [%d, %d] error = %d",
|
|
vr_index,
|
|
sctx->udp_fd[vr_index],
|
|
ipcom_errno);
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG3(DEBUG,
|
|
"close socket [%d, %d] error = %d",
|
|
vr_index,
|
|
sctx->udp_fd[vr_index],
|
|
ipcom_errno);
|
|
|
|
sctx->udp_fd[vr_index] = IP_INVALID_SOCKET;
|
|
}
|
|
}
|
|
|
|
/* close the RT adv socket */
|
|
if (rtadvctx->fd_icmp[vr_index] != IP_INVALID_SOCKET)
|
|
{
|
|
int ret = ipcom_socketclose(rtadvctx->fd_icmp[vr_index]);
|
|
if (ret < 0)
|
|
{
|
|
IPCOM_LOG3(ERR,
|
|
"close socket [%d, %d] error = %d",
|
|
vr_index,
|
|
rtadvctx->fd_icmp[vr_index],
|
|
ipcom_errno);
|
|
}
|
|
else
|
|
{
|
|
IPCOM_LOG3(DEBUG,
|
|
"close socket [%d, %d] error = %d",
|
|
vr_index,
|
|
rtadvctx->fd_icmp[vr_index],
|
|
ipcom_errno);
|
|
|
|
rtadvctx->fd_icmp[vr_index] = IP_INVALID_SOCKET;
|
|
}
|
|
}
|
|
|
|
/* detached the interface */
|
|
ipdhcpc6_if_context_update(rtctx->context->ifctx, vr_index);
|
|
|
|
return;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
nlh = IP_NLMSG_NEXT(nlh, length);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_nlsock_create
|
|
*===========================================================================
|
|
* Description: Allocate an rtsock
|
|
* Parameters: context - The DHCPC6 rtsock context.
|
|
* vr_index - vr index
|
|
* Returns: NA.
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_nlsock_create(Ipdhcpc6_rtsock_context_t *rtctx, int vr_index)
|
|
{
|
|
int cur_vr = ipcom_proc_vr_get();
|
|
|
|
ip_assert(IP_NULL != rtctx);
|
|
|
|
if ((rtctx->nl_fd[vr_index] == IP_INVALID_SOCKET)
|
|
&& (vr_index < IPCOM_VR_MAX))
|
|
{
|
|
struct Ip_sockaddr_nl nl_addr;
|
|
|
|
if (cur_vr != vr_index)
|
|
ipcom_proc_vr_set(vr_index);
|
|
|
|
rtctx->nl_fd[vr_index] = ipcom_socket(IP_AF_NETLINK,
|
|
IP_SOCK_RAW,
|
|
IP_NETLINK_ROUTE);
|
|
if (rtctx->nl_fd[vr_index] == IP_INVALID_SOCKET)
|
|
{
|
|
IPCOM_LOG1(ERR,
|
|
"Failed to bind on NL socket, errno = %d",
|
|
ipcom_errno);
|
|
goto errout;
|
|
}
|
|
|
|
if (ipcom_setsockopt(rtctx->nl_fd[vr_index],
|
|
IP_SOL_SOCKET,
|
|
IP_SO_X_VR,
|
|
&vr_index,
|
|
sizeof(vr_index)) != 0)
|
|
{
|
|
IPCOM_LOG2(WARNING,
|
|
"Failed to set VR %d on NL socket, errno = %d",
|
|
vr_index,
|
|
ipcom_errno);
|
|
goto errout;
|
|
}
|
|
|
|
ipcom_memset(&nl_addr, 0, sizeof(nl_addr));
|
|
nl_addr.nl_family = IP_AF_NETLINK;
|
|
IPCOM_SA_LEN_SET(&nl_addr, sizeof(nl_addr));
|
|
nl_addr.nl_groups = IP_NLMSG_GROUP_MASK(IP_RTNLGRP_RTAB)
|
|
| IP_NLMSG_GROUP_MASK(IP_RTNLGRP_LINK);
|
|
|
|
/* Bind socket */
|
|
if (ipcom_bind(rtctx->nl_fd[vr_index],
|
|
(struct Ip_sockaddr *)&nl_addr,
|
|
sizeof(nl_addr)) < 0)
|
|
{
|
|
IPCOM_LOG1(ERR,
|
|
"Failed to bind on NL socket, errno = %d",
|
|
ipcom_errno);
|
|
goto errout;
|
|
}
|
|
|
|
if (cur_vr != vr_index)
|
|
ipcom_proc_vr_set(cur_vr);
|
|
}
|
|
|
|
return;
|
|
|
|
errout:
|
|
if (rtctx->nl_fd[vr_index] != IP_INVALID_SOCKET)
|
|
{
|
|
ipcom_socketclose(rtctx->nl_fd[vr_index]);
|
|
rtctx->nl_fd[vr_index] = IP_INVALID_SOCKET;
|
|
}
|
|
|
|
if (cur_vr != vr_index)
|
|
ipcom_proc_vr_set(cur_vr);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_rtsock_context_alloc
|
|
*===========================================================================
|
|
* Description: Allocate an rtsock context
|
|
* Parameters: context - The DHCPC6 context.
|
|
* Returns: An rtsock context.
|
|
*
|
|
*/
|
|
IP_GLOBAL Ipdhcpc6_rtsock_context_t *
|
|
ipdhcpc6_rtsock_context_alloc(struct Ipdhcpc6_context *context)
|
|
{
|
|
Ipdhcpc6_rtsock_context_t *rtctx = ipcom_calloc(1, sizeof(*rtctx));
|
|
if (rtctx)
|
|
{
|
|
int vr_index;
|
|
|
|
rtctx->context = context;
|
|
|
|
for (vr_index = 0; vr_index < IPCOM_VR_MAX; vr_index++)
|
|
{
|
|
rtctx->nl_fd[vr_index] = IP_INVALID_SOCKET;
|
|
}
|
|
ipdhcpc6_nlsock_create(rtctx, 0);
|
|
}
|
|
|
|
return rtctx;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_rtsock_context_free
|
|
*===========================================================================
|
|
* Description: Free an rtsock context
|
|
* Parameters: rtctxp - Pointer to the DHCPC6 rtsock context.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_rtsock_context_free(Ipdhcpc6_rtsock_context_t **rtctxp)
|
|
{
|
|
Ipdhcpc6_rtsock_context_t *rtctx = *rtctxp;
|
|
if (rtctx)
|
|
{
|
|
int vr_index;
|
|
|
|
for (vr_index = 0; vr_index < IPCOM_VR_MAX; vr_index++)
|
|
{
|
|
if (rtctx->nl_fd[vr_index] != IP_INVALID_SOCKET)
|
|
{
|
|
ipcom_socketclose(rtctx->nl_fd[vr_index]);
|
|
rtctx->nl_fd[vr_index] = IP_INVALID_SOCKET;
|
|
}
|
|
}
|
|
ipdhcpc6_util_free(&rtctx);
|
|
}
|
|
*rtctxp = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_rtsock_context_fdset_init
|
|
*===========================================================================
|
|
* Description: Initialize all file descriptors of this context
|
|
* Parameters: rtctx - rtsock context
|
|
* rset - Read set to initialize.
|
|
* mfd - Maximum file descriptor.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_GLOBAL void
|
|
ipdhcpc6_rtsock_context_fdset_init(Ipdhcpc6_rtsock_context_t *rtctx,
|
|
Ip_fd_set *rset,
|
|
int *mfd)
|
|
{
|
|
int vr_index;
|
|
|
|
for (vr_index = 0; vr_index < IPCOM_VR_MAX; vr_index++)
|
|
{
|
|
if (rtctx->nl_fd[vr_index] != IP_INVALID_SOCKET)
|
|
{
|
|
*mfd = IP_MAX(*mfd, rtctx->nl_fd[vr_index]);
|
|
IP_FD_SET(rtctx->nl_fd[vr_index], rset);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipdhcpc6_rtsock_context_fdset_process
|
|
*===========================================================================
|
|
* Description: Process all file descriptors of this context
|
|
* Parameters: rtctx - rtsock context
|
|
* rset - Read set to initialize.
|
|
* status - Incoming status
|
|
* Returns: Outgoing status
|
|
*
|
|
*/
|
|
IP_GLOBAL int
|
|
ipdhcpc6_rtsock_context_fdset_process(Ipdhcpc6_rtsock_context_t *rtctx,
|
|
Ip_fd_set *rset,
|
|
int status)
|
|
{
|
|
int vr_index;
|
|
|
|
/* */
|
|
for (vr_index = 0; vr_index < IPCOM_VR_MAX; vr_index++)
|
|
{
|
|
if (rtctx->nl_fd[vr_index] != IP_INVALID_SOCKET)
|
|
{
|
|
if (IP_FD_ISSET(rtctx->nl_fd[vr_index], rset))
|
|
ipdhcpc6_nlsock_process(rtctx, vr_index);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|