Files
m241Neelima/components/ip_net2-6.9/ipcom/src/ipcom_waitif.c
T
2026-07-30 11:19:44 +05:30

391 lines
11 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $
* $Source: /home/interpeak/CVSRoot/ipcom/src/ipcom_waitif.c,v $
* $Author: hxie $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* ipcom_waitif.c contains an example of how to wait for an interface to
* acquire an IP address, e.g. when DHCP is used.
*
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipcom_config.h"
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPCOM
#ifdef IP_DEBUG
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG
#else
#define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_WARNING
#endif
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_err.h>
#include <ipcom_inet.h>
#include <ipcom_syslog.h>
#ifdef IPNET
#include <ipnet_routesock.h>
#include <ipcom_waitif.h>
/*
****************************************************************************
* 5 DEFINES
****************************************************************************
*/
/* Max # of interfaces to poll */
#define IPNET_WAITIF_MAXIF 16
/* Max timeout to wait for an address */
#define IPNET_WAITIF_TIMEOUT 60
/*
****************************************************************************
* 9 FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipcom_waitif_gifaddr
*===========================================================================
* Description: Get interface address.
* Parameters: fd - socket descriptor
* ifindex - Interface index.
* domain - The address domain.
* Returns: 0 = No address available, 1 = No address available, -1 = error.
*
*/
IP_STATIC int
ipcom_waitif_gifaddr(Ip_fd fd, int ifindex, int domain)
{
int ret = -1;
switch (domain)
{
case IP_AF_INET:
{
struct Ip_ifreq ifreq;
/* Get if name */
ipcom_memset(&ifreq, 0, sizeof(ifreq));
(void)ipcom_if_indextoname(ifindex, ifreq.ifr_name);
/* Get main address */
if (ipcom_socketioctl(fd, IP_SIOCGIFADDR, &ifreq) < 0)
{
if (ipcom_errno != IP_ERRNO_EADDRNOTAVAIL && ipcom_errno != IP_ERRNO_ENXIO)
{
IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_socketioctl(SIOCGIFADDR) failed, errno = %d", ipcom_errno);
}
}
else
{
struct Ip_in_addr network = ((struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr)->sin_addr;
if (network.s_addr != IP_INADDR_DEFAULT)
{
ret = 0;
}
}
break;
}
#ifdef IPCOM_USE_INET6
case IP_AF_INET6:
{
int len = IPNET_WAITIF_MAXIF * sizeof(struct Ip_ifreq);
char ifname[IP_IFNAMSIZ];
struct Ip_ifconf ifc;
char *buf = IP_NULL;
char *ptr;
/* Get if name */
(void)ipcom_if_indextoname(ifindex, ifname);
/* Get if data buffer */
if ((buf = ipcom_malloc(IPNET_WAITIF_MAXIF * sizeof(struct Ip_ifreq))) == IP_NULL)
{
IPCOM_LOG0(ERR, "ipcom_waitif :: Out of memory");
goto leave;
}
/* Enter buf in ifconf struct */
ifc.ifc_len = len;
ifc.ip_ifc_buf = buf;
if (ipcom_socketioctl(fd, IP_SIOCGIFCONF, &ifc) < 0)
{
IPCOM_LOG1(ERR, "ipcom_socketioctl(SIOCGIFCONF) failed, errno = %d\n", ipcom_errno);
goto leave;
}
/* Loop for all interfaces */
for (ptr = buf; ptr < buf + ifc.ifc_len; )
{
struct Ip_ifreq *ifr = (struct Ip_ifreq *)ptr;
char *cptr;
/* Calculate pointer to next if */
len = (int)IP_MAX(sizeof(struct Ip_sockaddr_in), ifr->ip_ifr_addr.sa_len);
ptr += sizeof(ifr->ifr_name) + len;
if ((cptr = ipcom_strchr(ifr->ifr_name, ':')) != IP_NULL)
{
*cptr = '\0';
}
/* Only for v6 addresses */
if (ipcom_strcmp(ifr->ifr_name, ifname) == 0 &&
ifr->ip_ifr_addr.sa_family == IP_AF_INET6)
{
struct Ip_sockaddr_in6 *in6 = (struct Ip_sockaddr_in6 *)&ifr->ip_ifr_addr;
if (!IP_IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr))
{
ret = 0;
break;
}
}
}
leave:
if (buf != IP_NULL)
{
ipcom_free(buf);
}
break;
}
#endif /* IPCOM_USE_INET6 */
}
return ret;
}
/*
*===========================================================================
* ipcom_waitif_address
*===========================================================================
* Description: check interface enabled dhcp to get an IP address assigned
* Parameters:
* Returns: 0 = success, -1 = error, and sets errno.
*
*/
IP_PUBLIC int
ipcom_waitif_address()
{
struct Ip_if_nameindex *oifrs, *ifrs;
struct Ip_ifreq ifreq;
int fd = IP_INVALID_SOCKET;
int ret = IPCOM_SUCCESS;
fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
if (fd == IP_INVALID_SOCKET)
return IPCOM_ERR_FAILED;
/* Search for interfaces preconfigured for dhcp */
ifrs = ipcom_if_nameindex();
if (ifrs == IP_NULL)
{
ipcom_socketclose(fd);
return IPCOM_ERR_FAILED;
}
for (oifrs = ifrs; ifrs && ifrs->if_name != IP_NULL; ifrs++)
{
/* Check if interface is up. */
ipcom_strncpy(ifreq.ifr_name, ifrs->if_name, sizeof(ifreq.ifr_name));
ifreq.ifr_name[sizeof(ifreq.ifr_name)-1] = '\0';
if (ipcom_socketioctl(fd, IP_SIOCGIFFLAGS,(char *)&ifreq) < 0)
{
IPCOM_LOG2(ERR,
"ipcom_waitif[%s] :: ipcom_ioctl(SIOCGIFFLAGS) failed, errno =%d",
ifrs->if_name, ipcom_errno);
continue;
}
if (IP_BIT_ISFALSE(ifreq.ifr_ifru.ifru_flags, IP_IFF_UP))
continue;
/* Check if DHCP is enabled for this interface. */
if (ipcom_socketioctl(fd, IP_SIOCXGDHCPRUNNING,(char *)&ifreq) < 0)
{
IPCOM_LOG2(ERR,
"ipcom_waitif[%s] :: ipcom_ioctl(IP_SIOCXGDHCPRUNNING) failed, errno =%d",
ifrs->if_name, ipcom_errno);
continue;
}
if (ifreq.ifr_ifru.ifru_opt == 1)
break; /*find the boot interface that enable dhcp flag*/
}
if(ifrs&&ifrs->if_name != IP_NULL)
ret = ipcom_waitif(ipcom_if_nametoindex(ifrs->if_name),IP_AF_INET);
ipcom_if_freenameindex(oifrs);
ipcom_socketclose(fd);
return ret;
}
/*
*===========================================================================
* ipcom_waitif
*===========================================================================
* Description: Wait for interface to get an IP address assigned.
* Parameters: ifindex - Index of the interface to wait for.
* 0 = any interface except loopback.
* domain - The address domain.
* Returns: 0 = success, -1 = error, and sets errno.
*
*/
IP_PUBLIC int
ipcom_waitif(int ifindex, int domain)
{
struct Ipnet_rs_msghdr rtmsg;
struct Ip_timeval stop;
struct Ip_timeval tv;
Ip_fd fd = IP_INVALID_SOCKET;
int ret = -1;
/* Check domain */
if (domain != IP_AF_INET
#ifdef IPCOM_USE_INET6
&& domain != IP_AF_INET6
#endif /* IPCOM_USE_INET6 */
)
{
IPCOM_LOG1(ERR, "ipcom_waitif :: invalid domain: %d", domain);
ipcom_errno_set(IP_ERRNO_EINVAL);
goto leave;
}
/* Get routing socket */
fd = ipcom_socket(IP_AF_ROUTE, IP_SOCK_RAW, 0);
if (fd == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_socket(ROUTE, RAW) failed, errno = %d", ipcom_errno);
goto leave;
}
/* Get stop time */
ipcom_microtime(&tv);
stop.tv_sec = tv.tv_sec + IPNET_WAITIF_TIMEOUT;
/* Loop and wait for address */
for (;;)
{
Ip_ssize_t length;
/* Check if address available */
if (ifindex == 0)
{
int i;
/* Any if will do */
for (i = 2; i < IPNET_WAITIF_MAXIF; i++)
{
if (ipcom_waitif_gifaddr(fd, i, domain) == 0)
{
ret = 0;
goto leave;
}
}
}
else if (ipcom_waitif_gifaddr(fd, ifindex, domain) == 0)
{
ret = 0;
goto leave;
}
again:
/* Get timeout time */
ipcom_microtime(&tv);
tv.tv_sec = stop.tv_sec - tv.tv_sec;
tv.tv_usec = 0;
if (tv.tv_sec <= 0)
{
ipcom_errno_set(IP_ERRNO_ETIMEDOUT);
goto leave;
}
/* Set receive timeout */
if (ipcom_setsockopt(fd, IP_SOL_SOCKET, IP_SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
{
IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_setsockopt(RCVTIMEO) failed, errno = %d", ipcom_errno);
goto leave;
}
/* Read routing message headers only (truncated read). */
length = ipcom_recv(fd, &rtmsg, sizeof(rtmsg), 0);
if (length == IP_SOCKERR)
{
if (ipcom_errno != IP_ERRNO_ETIMEDOUT && ipcom_errno != IP_ERRNO_EWOULDBLOCK)
{
IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_recv() failed, errno = %d", ipcom_errno);
}
goto leave;
}
/* Only bother about newaddr */
if (rtmsg.type != IPNET_RTM_NEWADDR)
{
goto again;
}
}
leave:
if (fd != IP_INVALID_SOCKET)
{
ipcom_socketclose(fd);
}
return ret;
}
#else
int ipcom_waitif_empty_file;
#endif
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/