/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipdhcpc6_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #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 **************************************************************************** */