original files of m241
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2006 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use
|
||||
* of this software may be licensed only pursuant to the terms
|
||||
* of an applicable Wind River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01a,12jun06,tlu Initial creation
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 1 DESCRIPTION
|
||||
****************************************************************************
|
||||
* Implementation of ripng shell command to use for IPRIPng show routines
|
||||
* or telnet shell management.
|
||||
*
|
||||
* 'ripngctrl' A command to print RIPng route entries and RIPng interfaces.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 2 CONFIGURATION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#include "ipripng_config.h"
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 3 INCLUDE FILES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#define IPCOM_USE_ANDORNOT
|
||||
#define IPCOM_USE_CLIB_PROTO
|
||||
#include <ipcom_clib.h>
|
||||
#include <ipcom_err.h>
|
||||
#include <ipcom_getopt.h>
|
||||
|
||||
#include "ipripng.h"
|
||||
|
||||
/* Syslog priority and facility. */
|
||||
#if defined(_WRS_CONFIG_IPRIPNG_SYSLOG_PRIORITY)
|
||||
#define IPCOM_SYSLOG_PRIORITY _WRS_CONFIG_IPRIPNG_SYSLOG_PRIORITY
|
||||
#else
|
||||
#define IPCOM_SYSLOG_PRIORITY IPCOM_SYSLOG_PRIO_DEFAULT
|
||||
#endif
|
||||
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPRIPNG
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 4 EXTERN PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 5 DEFINES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 6 TYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 7 LOCAL PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
IP_PUBLIC int ipripng_cmd_ripngctrl(int argc, char **argv);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 8 DATA
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 9 FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_cmd_ripngctrl
|
||||
*===========================================================================
|
||||
* Description: The 'ripngctrl' shell command. A command to print RIPng routes
|
||||
* and interfaces.
|
||||
* Parameters: Standard argc, argv
|
||||
* Returns: 0.
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC int
|
||||
ipripng_cmd_ripngctrl(int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(argc == 1)
|
||||
goto usage;
|
||||
|
||||
/*********** rtprint ***********/
|
||||
if(ipcom_strcmp(argv[1], "rtprint") == 0)
|
||||
{
|
||||
ipripng_rtdump();
|
||||
}
|
||||
|
||||
/*********** ifprint ***********/
|
||||
else if(ipcom_strcmp(argv[1], "ifprint") == 0)
|
||||
{
|
||||
ipripng_ifdump();
|
||||
}
|
||||
|
||||
/*********** ripngStart ********/
|
||||
else if(ipcom_strcmp(argv[1], "ripngStart") == 0)
|
||||
{
|
||||
if (argc != 4)
|
||||
goto usage;
|
||||
ripngStart((char *)argv[2], ipcom_atoi(argv[3]));
|
||||
}
|
||||
|
||||
/*********** ripngStop ********/
|
||||
else if(ipcom_strcmp(argv[1], "ripngStop") == 0)
|
||||
{
|
||||
ripngStop();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
goto usage;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
|
||||
ipcom_printf("usage: ripngctrl rtprint"IP_LF
|
||||
" ifprint"IP_LF
|
||||
" ripngStart '[options]' [priority]"IP_LF
|
||||
" ripngStop"IP_LF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* END OF FILE
|
||||
****************************************************************************
|
||||
*/
|
||||
@@ -0,0 +1,828 @@
|
||||
/*
|
||||
* Copyright 2006 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use
|
||||
* of this software may be licensed only pursuant to the terms
|
||||
* of an applicable Wind River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01d,14mar11,xhs Fix defect WIND00260151, stack overflow
|
||||
01c,24jan07,tlu Fix gnu compile warning
|
||||
01b,17nov06,tlu Define the stack size for the RIPng task and reset daemon_started
|
||||
to IP_FALSE at function ripngStop()
|
||||
01a,12jun06,tlu Initial creation
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 1 DESCRIPTION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 2 CONFIGURATION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 3 INCLUDE FILES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#define IPCOM_USE_CLIB_PROTO
|
||||
#include <ipcom_type.h>
|
||||
#include <ipcom_cstyle.h>
|
||||
#include <ipcom_clib.h>
|
||||
#include <ipcom_err.h>
|
||||
#include <ipcom_os.h>
|
||||
#include <ipcom_sock.h>
|
||||
#include <ipcom_sock2.h>
|
||||
#include <ipcom_inet.h>
|
||||
#include <ipcom_syslog.h>
|
||||
#include <ipcom_ipd.h>
|
||||
#include <ipcom_errno.h>
|
||||
|
||||
#include <ipnet_config.h>
|
||||
#include <ipnet.h>
|
||||
#include <ipnet_cmd.h>
|
||||
#include <ipnet_h.h>
|
||||
#include <ipnet_ip6.h>
|
||||
|
||||
#include "ipripng.h"
|
||||
#include "ipripng_constant.h"
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 4 DEFINES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/* Syslog priority and facility. */
|
||||
#ifdef IPCOM_SYSLOG_PRIORITY
|
||||
#undef IPCOM_SYSLOG_PRIORITY
|
||||
#endif
|
||||
#if defined(_WRS_CONFIG_IPRIPNG_SYSLOG_PRIORITY)
|
||||
#define IPCOM_SYSLOG_PRIORITY _WRS_CONFIG_IPRIPNG_SYSLOG_PRIORITY
|
||||
#else
|
||||
#define IPCOM_SYSLOG_PRIORITY IPCOM_SYSLOG_PRIO_DEFAULT
|
||||
#endif
|
||||
#ifdef IPCOM_SYSLOG_FACILITY
|
||||
#undef IPCOM_SYSLOG_FACILITY
|
||||
#endif
|
||||
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPRIPNG
|
||||
|
||||
#ifndef IPNET
|
||||
#error IPRIPNG_REQUIRES_IPNET
|
||||
#endif
|
||||
|
||||
#define IPNET_IF_LOOPBACK_INDEX 1 /* The index of the loopback interface */
|
||||
|
||||
#define RIPTASKSTACK 20000 /* RIPng task stack size */
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 5 TYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 6 EXTERN PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 7 LOCAL PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
IP_STATIC Ip_err ipripng_add_route_rtsock(Ipripng_rt *rrt, const struct in6_addr *gw, struct ifc *ifcp);
|
||||
IP_STATIC Ip_err ipripng_delete_route_rtsock(struct netinfo6 *np, const struct in6_addr *gw, Ip_bool proto_set);
|
||||
|
||||
IPCOM_PROCESS(ipripngd);
|
||||
|
||||
IP_PUBLIC Ip_err ipripng_create(void);
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 8 DATA
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
IP_STATIC Ip_bool daemon_started = IP_FALSE;
|
||||
IP_PUBLIC Ip_bool ripngStopFlag;
|
||||
IP_PUBLIC char ripng_cmdString[IPRIPNG_MAXARGS + 2];
|
||||
IP_STATIC int priv_ripng_seq;
|
||||
|
||||
|
||||
#if IPRIPNG_SYSLOG_PRIORITY >= IPCOM_LOG_DEBUG2
|
||||
|
||||
IP_STATIC Ipnet_cmd_int_str_map iprip_rtm_map[] =
|
||||
{
|
||||
{ IPNET_RTM_ADD, "ADD" },
|
||||
{ IPNET_RTM_DELETE, "DELETE" },
|
||||
{ IPNET_RTM_CHANGE, "CHANGE" },
|
||||
{ IPNET_RTM_GET, "GET" },
|
||||
{ IPNET_RTM_LOOSING, "LOOSING" },
|
||||
{ IPNET_RTM_REDIRECT, "REDIRECT" },
|
||||
{ IPNET_RTM_MISS, "MISS" },
|
||||
{ IPNET_RTM_LOCK, "LOCK" },
|
||||
{ IPNET_RTM_RESOLVE, "RESOLVE" },
|
||||
{ IPNET_RTM_NEWADDR, "NEWADDR" },
|
||||
{ IPNET_RTM_DELADDR, "DELADDR" },
|
||||
{ IPNET_RTM_IFINFO, "IFINFO" },
|
||||
{ -1, IP_NULL }
|
||||
};
|
||||
|
||||
IP_STATIC Ipnet_cmd_int_str_map iprip_rta_map[] =
|
||||
{
|
||||
{ IPNET_RTAX_DST, "DST" },
|
||||
{ IPNET_RTAX_GATEWAY, "GATEWAY" },
|
||||
{ IPNET_RTAX_NETMASK, "NETMASK" },
|
||||
{ IPNET_RTAX_GENMASK, "GENMASK" },
|
||||
{ IPNET_RTAX_IFP, "IFP" },
|
||||
{ IPNET_RTAX_IFA, "IFA" },
|
||||
{ IPNET_RTAX_AUTHOR, "AUTHOR" },
|
||||
{ IPNET_RTAX_BRD, "BRD" },
|
||||
{ -1, IP_NULL }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 9 LOCAL FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_rtsock_add
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_err
|
||||
ipripng_rtsock_add(Ipripng_rt *rrt, const struct in6_addr *gw, struct ifc *ifcp)
|
||||
{
|
||||
struct netinfo6 *np;
|
||||
Ip_u8 buffer[IP_BUFSIZ], buf1[IP_INET6_ADDRSTRLEN], buf2[IP_INET6_ADDRSTRLEN];
|
||||
struct Ipnet_rt_msghdr *rtm;
|
||||
struct Ip_sockaddr_in6 *sin;
|
||||
Ip_size_t len;
|
||||
char buf3[IP_INET6_ADDRSTRLEN];
|
||||
Ip_fd ripng_rtsock;
|
||||
|
||||
np = &rrt->rrt_info;
|
||||
if (ipcom_inet_ntop(IP_AF_INET6, (void *)gw, (char *)buf1, sizeof(buf1)) == IP_NULL)
|
||||
buf1[0] = '\0'; /* So doesn't display garbage */
|
||||
if (ipcom_inet_ntop(IP_AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2)) == IP_NULL)
|
||||
buf2[0] = '\0'; /* So doesn't display garbage */
|
||||
if (ipcom_inet_ntop(IP_AF_INET6, &(np->rip6_dest), buf3, sizeof (buf3)) == IP_NULL)
|
||||
buf3[0] = '\0'; /* So doesn't display garbage */
|
||||
IPCOM_LOG5(INFO, "ADD: %s/%d gw %s [%d] ifa %s",
|
||||
buf3, np->rip6_plen, buf1,
|
||||
np->rip6_metric - 1, buf2);
|
||||
if (ipripng_nflag())
|
||||
return 0;
|
||||
|
||||
ipcom_memset(buffer, 0, sizeof(buffer));
|
||||
rtm = (struct Ipnet_rt_msghdr *)buffer;
|
||||
rtm->rtm_type = IPNET_RTM_ADD;
|
||||
rtm->rtm_version = IPNET_RTM_VERSION;
|
||||
rtm->rtm_seq = (Ip_u32)++priv_ripng_seq;
|
||||
rtm->rtm_pid = ipcom_getpid();
|
||||
rtm->rtm_flags = rrt->rrt_flags;
|
||||
if ((rtm->rtm_flags & IPNET_RTF_HOST) == 0)
|
||||
rtm->rtm_addrs = IPNET_RTA_DST | IPNET_RTA_GATEWAY | IPNET_RTA_NETMASK;
|
||||
else
|
||||
rtm->rtm_addrs = IPNET_RTA_DST | IPNET_RTA_GATEWAY;
|
||||
rtm->rtm_rmx.rmx_hopcount = (Ip_u32)(np->rip6_metric - 1);
|
||||
rtm->rtm_inits = IPNET_RTV_HOPCOUNT;
|
||||
sin = (struct Ip_sockaddr_in6 *)&buffer[sizeof(struct Ipnet_rt_msghdr)];
|
||||
/* Destination */
|
||||
sin->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
||||
sin->sin6_family = IP_AF_INET6;
|
||||
sin->sin6_addr = np->rip6_dest;
|
||||
RT_PROTO_SET (sin, M2_ipRouteProto_rip);
|
||||
TOS_SET (sin, 0);
|
||||
sin = (struct Ip_sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));
|
||||
/* Gateway */
|
||||
sin->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
||||
sin->sin6_family = IP_AF_INET6;
|
||||
sin->sin6_addr = *gw;
|
||||
sin = (struct Ip_sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));
|
||||
if ((rtm->rtm_flags & IPNET_RTF_HOST) == 0)
|
||||
{
|
||||
/* Netmask */
|
||||
sin->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
||||
sin->sin6_family = IP_AF_INET6;
|
||||
sin->sin6_addr = *(plen2mask(np->rip6_plen));
|
||||
sin = (struct Ip_sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));
|
||||
}
|
||||
|
||||
len = (Ip_size_t)((char *)sin - (char *)buffer);
|
||||
rtm->rtm_msglen = (Ip_u16)len;
|
||||
ripng_rtsock = ipripng_rtsocket();
|
||||
if (ipcom_socketwrite(ripng_rtsock, (char *)buffer, len) > 0)
|
||||
return IPCOM_SUCCESS;
|
||||
|
||||
if (ipcom_errno == IP_ERRNO_EEXIST) {
|
||||
IPCOM_LOG3(WARNING, "ADD: Route already exists %s/%d gw %s",
|
||||
buf3, np->rip6_plen, buf1);
|
||||
} else {
|
||||
IPCOM_LOG1(WARNING, "Can not write to ripng_rtsock (addroute): %s",
|
||||
ipcom_strerror(ipcom_errno));
|
||||
}
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_rtsock_del
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_err
|
||||
ipripng_rtsock_del(struct netinfo6 *np, const struct in6_addr *gw, Ip_bool proto_set)
|
||||
{
|
||||
Ip_u8 buf[IP_BUFSIZ], buf2[IP_INET6_ADDRSTRLEN];
|
||||
struct Ipnet_rt_msghdr *rtm;
|
||||
struct Ip_sockaddr_in6 *sin;
|
||||
Ip_size_t len;
|
||||
char buf3[IP_INET6_ADDRSTRLEN];
|
||||
Ip_fd ripng_rtsock;
|
||||
|
||||
|
||||
if (ipcom_inet_ntop(IP_AF_INET6, (void *)gw, (char *)buf2, sizeof(buf2)) == IP_NULL)
|
||||
buf2[0] = '\0'; /* So doesn't display garbage */
|
||||
if (ipcom_inet_ntop(IP_AF_INET6, &np->rip6_dest, buf3, sizeof (buf3)) == IP_NULL)
|
||||
buf3[0] = '\0'; /* So doesn't display garbage */
|
||||
IPCOM_LOG3(INFO, "DEL: %s/%d gw %s", buf3,
|
||||
np->rip6_plen, buf2);
|
||||
if (ipripng_nflag())
|
||||
return 0;
|
||||
|
||||
ipcom_memset(buf, 0, sizeof(buf));
|
||||
rtm = (struct Ipnet_rt_msghdr *)buf;
|
||||
rtm->rtm_type = IPNET_RTM_DELETE;
|
||||
rtm->rtm_version = IPNET_RTM_VERSION;
|
||||
rtm->rtm_seq = (Ip_u32)++priv_ripng_seq;
|
||||
rtm->rtm_pid = ipcom_getpid();
|
||||
rtm->rtm_flags = IPNET_RTF_UP | IPNET_RTF_GATEWAY;
|
||||
if (np->rip6_plen == sizeof(struct in6_addr) * 8)
|
||||
{
|
||||
rtm->rtm_flags |= IPNET_RTF_HOST;
|
||||
rtm->rtm_addrs = IPNET_RTA_DST | IPNET_RTA_GATEWAY;
|
||||
}
|
||||
else
|
||||
rtm->rtm_addrs = IPNET_RTA_DST | IPNET_RTA_GATEWAY | IPNET_RTA_NETMASK;
|
||||
sin = (struct Ip_sockaddr_in6 *)&buf[sizeof(struct Ipnet_rt_msghdr)];
|
||||
/* Destination */
|
||||
sin->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
||||
sin->sin6_family = IP_AF_INET6;
|
||||
sin->sin6_addr = np->rip6_dest;
|
||||
if (proto_set)
|
||||
{
|
||||
RT_PROTO_SET (sin, M2_ipRouteProto_rip);
|
||||
TOS_SET (sin, 0);
|
||||
}
|
||||
sin = (struct Ip_sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));
|
||||
/* Gateway */
|
||||
sin->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
||||
sin->sin6_family = IP_AF_INET6;
|
||||
sin->sin6_addr = *gw;
|
||||
sin = (struct Ip_sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));
|
||||
if ((rtm->rtm_flags & IPNET_RTF_HOST) == 0)
|
||||
{
|
||||
/* Netmask */
|
||||
sin->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
||||
sin->sin6_family = IP_AF_INET6;
|
||||
sin->sin6_addr = *(plen2mask(np->rip6_plen));
|
||||
sin = (struct Ip_sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));
|
||||
}
|
||||
|
||||
len = (Ip_size_t)((char *)sin - (char *)buf);
|
||||
rtm->rtm_msglen = (Ip_u16)len;
|
||||
|
||||
ripng_rtsock = ipripng_rtsocket();
|
||||
if (ipcom_socketwrite(ripng_rtsock, (char *)buf, len) >= 0)
|
||||
return IPCOM_SUCCESS;
|
||||
|
||||
if (ipcom_errno == IP_ERRNO_ESRCH) {
|
||||
IPCOM_LOG3(WARNING, "RTDEL: Route does not exist: %s/%d gw %s",
|
||||
buf3, np->rip6_plen, buf2);
|
||||
} else {
|
||||
IPCOM_LOG1(WARNING, "Can not write to ripng_rtsock (delroute): %s",
|
||||
ipcom_strerror(ipcom_errno));
|
||||
}
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* iprip_add_route_rtsock
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_err
|
||||
ipripng_add_route_rtsock(Ipripng_rt *rrt, const struct in6_addr *gw, struct ifc *ifcp)
|
||||
{
|
||||
return ipripng_rtsock_add(rrt, gw, ifcp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_delete_route_rtsock
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_STATIC Ip_err
|
||||
ipripng_delete_route_rtsock(struct netinfo6 *np, const struct in6_addr *gw, Ip_bool proto_set)
|
||||
{
|
||||
return ipripng_rtsock_del(np, gw, proto_set);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripngd
|
||||
*===========================================================================
|
||||
* Description: RIPng daemon
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IPCOM_PROCESS(ipripngd)
|
||||
{
|
||||
Ip_err ret;
|
||||
Ipripng_open conf;
|
||||
struct ifc *ifcp;
|
||||
Ip_bool ipripng_init_ok = IP_FALSE;
|
||||
Ip_bool ipripng_open_ok = IP_FALSE;
|
||||
int num;
|
||||
Ip_fd max;
|
||||
Ip_fd udp_fd = IP_INVALID_SOCKET;
|
||||
Ip_fd rt_fd = IP_INVALID_SOCKET;
|
||||
Ip_fd_set read_set, fds;
|
||||
Ip_fd ipd_fd = IP_INVALID_SOCKET;
|
||||
struct Ip_timeval tv, *ptv = IP_NULL;
|
||||
|
||||
|
||||
ipcom_proc_init();
|
||||
|
||||
IPCOM_LOG0(INFO, "ipripngd :: starting");
|
||||
|
||||
daemon_started = IP_TRUE;
|
||||
ripngStopFlag = IP_FALSE;
|
||||
|
||||
/***** Initialize IPRIPng. *****/
|
||||
ret = ipripng_init();
|
||||
if(ret != IPCOM_SUCCESS)
|
||||
{
|
||||
IPCOM_LOG1(ERR, "ipripngd :: ipripng_init() failed, err = %ld", ret);
|
||||
goto badout;
|
||||
}
|
||||
ipripng_init_ok = IP_TRUE;
|
||||
|
||||
|
||||
/* Open udp and routing sockets */
|
||||
ret = ipripng_initsocks();
|
||||
if (ret != IPCOM_SUCCESS) {
|
||||
IPCOM_LOG1(ERR, "ipripngd :: ipripng_initsocks() failed, err = %ld", ret);
|
||||
goto badout;
|
||||
}
|
||||
udp_fd = ipripng_ripsocket();
|
||||
rt_fd = ipripng_rtsocket();
|
||||
|
||||
|
||||
/***** Open and configure IPRIPNG. *****/
|
||||
conf.add_route = ipripng_add_route_rtsock;
|
||||
conf.delete_route = ipripng_delete_route_rtsock;
|
||||
conf.conf[0] = IP_TAG_END;
|
||||
ret = ipripng_open(&conf);
|
||||
if(ret != IPCOM_SUCCESS) {
|
||||
IPCOM_LOG1(ERR, "ipripngd :: ipripng_open() failed, err = %ld", ret);
|
||||
goto badout;
|
||||
}
|
||||
ipripng_open_ok = IP_TRUE;
|
||||
|
||||
|
||||
/* Initialize RIPng interfaces */
|
||||
/* Check ripngStop() wasn't called as below can sleep */
|
||||
if ((ipripng_ifconfig() != IPCOM_SUCCESS) || ripngStopFlag) {
|
||||
IPCOM_LOG1(ERR, "ipripngd :: ipripng_ifconfig() failed, err = %ld", ret);
|
||||
goto badout;
|
||||
}
|
||||
|
||||
|
||||
/* Add interface routes */
|
||||
for (ifcp = ipripng_ifhead(); ifcp; ifcp = ifcp->ifc_next)
|
||||
if (ipripng_ifrt(ifcp, 0) < 0) {
|
||||
IPCOM_LOG0(ERR, "ipripngd :: ipripng_ifrt() failed");
|
||||
goto badout;
|
||||
}
|
||||
|
||||
/* Process -A and -O filter options */
|
||||
if (ipripng_filterconfig() != IPCOM_SUCCESS) {
|
||||
IPCOM_LOG0(ERR, "ipripngd :: ipripng_filterconfig() failed");
|
||||
goto badout;
|
||||
}
|
||||
|
||||
/* Add kernel routes */
|
||||
if (ipripng_krtread(0) != IPCOM_SUCCESS) {
|
||||
IPCOM_LOG0(ERR, "ipripngd :: ipripng_krtread() failed");
|
||||
goto badout;
|
||||
}
|
||||
|
||||
|
||||
/* IPD init. */
|
||||
if(ipcom_ipd_init("ipripng", IPCOM_SUCCESS, &ipd_fd) != IPCOM_SUCCESS) {
|
||||
ipcom_printf("ipripngd :: ipcom_ipd_init() failed");
|
||||
goto badout;
|
||||
}
|
||||
|
||||
/* Send the initial request to RIPng interfaces */
|
||||
for (ifcp = ipripng_ifhead(); ifcp; ifcp = ifcp->ifc_next) {
|
||||
if (iff_find(ifcp, 'N'))
|
||||
continue;
|
||||
if (ifcp->ifc_index > 0 && (ifcp->ifc_flags & IP_IFF_UP) &&
|
||||
((ifcp->ifc_flags & IP_IFF_LOOPBACK) == 0))
|
||||
{
|
||||
ipripng_sendrequest(ifcp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***** Input loop. *****/
|
||||
max = IP_MAX(udp_fd, rt_fd);
|
||||
max = IP_MAX(max, ipd_fd);
|
||||
IP_FD_ZERO(&fds);
|
||||
IP_FD_SET(udp_fd, &fds);
|
||||
IP_FD_SET(rt_fd, &fds);
|
||||
IP_FD_SET(ipd_fd, &fds);
|
||||
|
||||
/* set the timeout value */
|
||||
ipcom_memset(&tv, 0, sizeof(struct Ip_timeval));
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
ptv = &tv;
|
||||
|
||||
IPCOM_LOG0(INFO, "**** Started ****");
|
||||
while (1) {
|
||||
/* Check ripngStop() wasn't called */
|
||||
if (ripngStopFlag) {
|
||||
IPCOM_LOG0(INFO, "RIPng requested to close. Closing down");
|
||||
goto badout;
|
||||
}
|
||||
|
||||
read_set = fds;
|
||||
num = ipcom_socketselect(max + 1, &read_set, IP_NULL, IP_NULL, ptv);
|
||||
|
||||
|
||||
if (ripngStopFlag) {
|
||||
IPCOM_LOG0(INFO, "RIPng requested to close. Closing down");
|
||||
goto badout;
|
||||
}
|
||||
|
||||
switch (num) {
|
||||
case -1:
|
||||
|
||||
IPCOM_LOG0(ERR, "ipripngd select error");
|
||||
goto badout;
|
||||
|
||||
case 0:
|
||||
continue;
|
||||
|
||||
default:
|
||||
if (IP_FD_ISSET(udp_fd, &read_set)) {
|
||||
IPCOM_LOG0 (INFO, "RIPng message received");
|
||||
if (ipripng_riprecv() != IPCOM_SUCCESS) {
|
||||
goto badout;
|
||||
}
|
||||
}
|
||||
if (IP_FD_ISSET(rt_fd, &read_set)) {
|
||||
IPCOM_LOG0(INFO, "Message received on routing socket");
|
||||
if (ipripng_rtrecv() != IPCOM_SUCCESS) {
|
||||
goto badout;
|
||||
}
|
||||
}
|
||||
if (IP_FD_ISSET(ipd_fd, &read_set)) {
|
||||
int event;
|
||||
|
||||
event = ipcom_ipd_input(ipd_fd);
|
||||
switch(event) {
|
||||
case IPCOM_IPD_EVENT_KILL:
|
||||
IPCOM_LOG0(INFO, "received IPD kill message");
|
||||
goto badout;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} /* switch */
|
||||
} /* while */
|
||||
|
||||
badout:
|
||||
if(ipd_fd == IP_INVALID_SOCKET)
|
||||
(void)ipcom_ipd_init("ipripng", IPCOM_ERR_FAILED, &ipd_fd);
|
||||
|
||||
if(ipripng_open_ok)
|
||||
(void)ipripng_close();
|
||||
if(ipripng_init_ok)
|
||||
(void)ipripng_exit();
|
||||
|
||||
(void)ipcom_ipd_exit("ipripng", ipd_fd);
|
||||
|
||||
IPCOM_LOG0(INFO, "ipripngd :: ending");
|
||||
ipcom_proc_exit();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 10 PUBLIC FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_create
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipripng_create(void)
|
||||
{
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* ripngStart - Start the RIPng system
|
||||
*
|
||||
* This routine starts the RIPng routing daemon which supports RIPng over IPv6.
|
||||
*
|
||||
* <cmdString> is a string that can contain a selection of parameters as follows:
|
||||
*
|
||||
*
|
||||
* -a Enables aging of the statically defined routes. With this option,
|
||||
* any statically defined routes will be removed unless corresponding
|
||||
* updates arrive as if the routes are received at startup.
|
||||
*
|
||||
* -A prefix/preflen,if1[,if2...]
|
||||
* This option is used for aggregating routes. prefix/preflen specifies
|
||||
* the prefix and the prefix length of the aggregated route. When
|
||||
* advertising routes, RIPng filters specific routes covered by the
|
||||
* aggregate, and advertises the aggregated route prefix/preflen, to
|
||||
* the interfaces specified in the comma-separated interface list,
|
||||
* if1[,if2...]. RIPng creates a static route to prefix/preflen with
|
||||
* RTF_REJECT flag, into the kernel routing table.
|
||||
*
|
||||
* -d Enables output of debugging messages.
|
||||
*
|
||||
* -D Enables extensive output of debugging messages.
|
||||
*
|
||||
* -h Disable split horizon processing by default. Unless interfaces are
|
||||
* explicitly configured using -x/y/z, all new interfaces have Split
|
||||
* Horizon with Poison Reverse enabled. We can use -h to disable
|
||||
* this so that all new interfaces have Split Horizon disabled.
|
||||
* See also -p which causes all new interfaces to default to Split
|
||||
* Horizon without Poison Reverse. Do not specify -p or -h if you wish
|
||||
* to default all new interfaces to Poison Reverse.
|
||||
*
|
||||
* -l Exchange site local routes. By default, RIPng will not exchange
|
||||
* site local routes for safety reasons. This is because semantics of
|
||||
* site local address space is rather vague (specification is still
|
||||
* being worked on), and there is no good way to define site local
|
||||
* boundary. With -l option, RIPng will exchange site local routes as
|
||||
* well. It must not be used on site boundary routers, since -l option
|
||||
* assumes that all interfaces are in the same site.
|
||||
*
|
||||
* -L prefix/preflen,if1[,if2...]
|
||||
* Filter incoming routes from interfaces if1,[if2...]. RIPng will
|
||||
* accept incoming routes that are in prefix/preflen. If multiple -L
|
||||
* options are specified, any routes that match one of the options is
|
||||
* accepted. ::/0 is treated specially as default route, not "any
|
||||
* route that has longer prefix length than, or equal to 0". If you would
|
||||
* like to accept any route, specify no -L option. For example, with
|
||||
* "-L 3ffe::/16,if1 -L ::/0,if1". RIPng will accept default route and
|
||||
* routes in 6bone test address, but no others.
|
||||
*
|
||||
* -N if1[,if2...]
|
||||
* Do not listen to, or advertise, route from/to interfaces specified by
|
||||
* if1,[if2...].
|
||||
*
|
||||
* -O prefix/preflen,if1[,if2...]
|
||||
* Restrict route advertisement toward interfaces specified by
|
||||
* if1,[if2...]. With this option RIPng will only advertise routes that
|
||||
* matches prefix/preflen.
|
||||
*
|
||||
* -p Disable Poison Reverse by default. Specifying this causes all new
|
||||
* interfaces to use Split Horizon without Poison Reverse. To disable
|
||||
* Split Horizon altogether use -h. Note that this does not affect
|
||||
* interfaces which are explicitly configured using -x/y/z. -p and -h
|
||||
* are only used to set the default mode for interfaces which are not
|
||||
* explicitly configured. To use Poison Reverse by default, do not
|
||||
* specify either -p or -h.
|
||||
*
|
||||
* -q Puts RIPng in listen only mode. No advertisements are sent.
|
||||
*
|
||||
* -r addr1[,addr2...]
|
||||
* Restricted Neighbor List. Only accept responses from the routers
|
||||
* specified in the address list (addr1...).
|
||||
*
|
||||
* -s Makes RIPng advertise the statically defined routes which exist in the
|
||||
* kernel routing table when RIPng invoked. Announcements obey the regular
|
||||
* split horizon rule.
|
||||
*
|
||||
* -S This option is the same as -s option except that no split horizon rule
|
||||
* is applied.
|
||||
*
|
||||
* -T if1[,if2...]
|
||||
* Advertise only default route, toward if1,[if2...].
|
||||
*
|
||||
* -t tag
|
||||
* Attach route tag tag to originated route entries. tag can be decimal,
|
||||
* octal prefixed by 0, or hexadecimal prefixed by 0x.
|
||||
*
|
||||
* -x if1[,if2...]
|
||||
* Enable Poison Reverse Processing for these interfaces.
|
||||
*
|
||||
* -y if1[,if2...]
|
||||
* Enable Split Horizon (without Poison Reverse) for these interfaces.
|
||||
*
|
||||
* -z if1[,if2...]
|
||||
* Disable Split Horizon altogether on these interfaces.
|
||||
*
|
||||
*
|
||||
* <priority> specifies the priority of the main RIPng task: tRipTask. Specifying
|
||||
* no priority (0) uses the default priority of 100. Note that the RIPng task
|
||||
* priorities must be lower (worse) than tNetTask's priority.
|
||||
*
|
||||
* It may be called from the VxWorks shell as follows:
|
||||
*
|
||||
* .CS
|
||||
* -> ripngStart "[options]", [pri]
|
||||
* .CE
|
||||
*
|
||||
* Or to accept the default priority:
|
||||
*
|
||||
* .CS
|
||||
* -> ripngStart "[options]"
|
||||
* .CE
|
||||
*
|
||||
* A supporting task (tRipDog) is always created with a higher priority than
|
||||
* tRipTask. It's priority is equal to ((priority of tRipTask) - 1).
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
* ERRNO: ENOMEM, EALREADY
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err ripngStart
|
||||
(
|
||||
char * cmdString, /* String of options */
|
||||
int priority /* Required priority level for tRipngTask */
|
||||
)
|
||||
{
|
||||
Ip_err ret = IPCOM_SUCCESS;
|
||||
Ipcom_proc_attr attr;
|
||||
|
||||
|
||||
if(priority==0 || priority > IPCOM_PRIORITY_MAX)
|
||||
priority = IPCOM_PRIORITY_DEFAULT - 1;
|
||||
|
||||
/* Check not already running */
|
||||
if (daemon_started == IP_TRUE) {
|
||||
IPCOM_LOG0(ERR, "ripngStart: RIPng already running");
|
||||
return IPCOM_ERR_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
ipcom_proc_attr_init(&attr);
|
||||
attr.priority = priority;
|
||||
attr.stacksize = RIPTASKSTACK;
|
||||
|
||||
ipcom_strcpy(ripng_cmdString, " ");
|
||||
if (cmdString != IP_NULL) {
|
||||
if (ipcom_strlen(cmdString) >= sizeof(ripng_cmdString)) {
|
||||
IPCOM_LOG2(ERR, "ripngStart: length of %s exceeds %d", cmdString, sizeof(ripng_cmdString)-1);
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
ipcom_strcpy(ripng_cmdString, cmdString);
|
||||
}
|
||||
ret = ipcom_proc_acreate(RIPTASKNAME, ipripngd, &attr, IP_NULL);
|
||||
|
||||
if (ret != IPCOM_SUCCESS) {
|
||||
IPCOM_LOG0(ERR, "ripngStart: Failed on ipcom_proc_acreate");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* ripngStop - Stop the RIPng system
|
||||
*
|
||||
* This routine stops the RIPng routing daemon.
|
||||
*
|
||||
* It may be used to reconfigure RIPng by stopping it and restarting with
|
||||
* ripngStart() and different parameters.
|
||||
*
|
||||
* It may be called from the VxWorks shell as follows:
|
||||
*
|
||||
* .CS
|
||||
* -> ripngStop
|
||||
* .CE
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
* ERRNO:
|
||||
*
|
||||
*/
|
||||
void ripngStop (void)
|
||||
{
|
||||
|
||||
/* Check whether RIPng already running */
|
||||
if (daemon_started == IP_FALSE) {
|
||||
IPCOM_LOG0(ERR, "ripngStop: RIPng not started yet");
|
||||
return;
|
||||
}
|
||||
|
||||
ripngStopFlag = IP_TRUE;
|
||||
daemon_started = IP_FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_start
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipripng_start(void)
|
||||
{
|
||||
Ip_err ret;
|
||||
Ipcom_proc_attr attr;
|
||||
|
||||
ipcom_proc_attr_init(&attr);
|
||||
|
||||
ipcom_strcpy(ripng_cmdString, " ");
|
||||
attr.priority = IPCOM_PRIORITY_DEFAULT - 1;
|
||||
attr.stacksize = IPCOM_PROC_STACK_LARGE;
|
||||
ret = ipcom_proc_acreate(RIPTASKNAME, ipripngd, &attr, IP_NULL);
|
||||
ip_assert(ret == IPCOM_SUCCESS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* END OF FILE
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Copyright 2006 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use
|
||||
* of this software may be licensed only pursuant to the terms
|
||||
* of an applicable Wind River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01i,05nov08,rme Used 'ipripng_sflag' in 'tobeadv' (WIND00141137)
|
||||
01c,27apr07,tlu Remove double variable usage, changed to long
|
||||
01b,24jan07,kch Remove VxWorks header file, convert VxWorks typedefs
|
||||
and functions to IPCOM equivalent
|
||||
01a,12jun06,tlu Initial creation
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 1 DESCRIPTION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 2 CONFIGURATION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#include "ipripng_config.h"
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 3 INCLUDE FILES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#define IPCOM_USE_CLIB_PROTO
|
||||
#include <ipcom_type.h>
|
||||
#include <ipcom_cstyle.h>
|
||||
#include <ipcom_clib.h>
|
||||
#include <ipcom_err.h>
|
||||
#include <ipcom_os.h>
|
||||
#include <ipcom_sock.h>
|
||||
#include <ipcom_sock2.h>
|
||||
#include <ipcom_inet.h>
|
||||
#include <ipcom_syslog.h>
|
||||
#include <ipcom_sysctl.h>
|
||||
#include <ipcom_shell.h>
|
||||
|
||||
#include <ipnet_config.h>
|
||||
#include <ipnet.h>
|
||||
#include <ipnet_routesock.h>
|
||||
#include <ipnet_cmd.h>
|
||||
|
||||
#include "ipripng.h"
|
||||
#include "ipripng_constant.h"
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 4 DEFINES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/* Syslog priority and facility. */
|
||||
#if defined(_WRS_CONFIG_IPRIPNG_SYSLOG_PRIORITY)
|
||||
#define IPCOM_SYSLOG_PRIORITY _WRS_CONFIG_IPRIPNG_SYSLOG_PRIORITY
|
||||
#else
|
||||
#define IPCOM_SYSLOG_PRIORITY IPCOM_SYSLOG_PRIO_DEFAULT
|
||||
#endif
|
||||
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPRIPNG
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 5 TYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 6 EXTERN PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 7 LOCAL PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 8 DATA
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 9 STATIC FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 10 GLOBAL FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipripng_allocopy
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL char *
|
||||
ipripng_allocopy(char *p)
|
||||
{
|
||||
char *q = (char *)ipcom_malloc(strlen(p) + 1);
|
||||
|
||||
if (q == IP_NULL)
|
||||
return IP_NULL;
|
||||
|
||||
ipcom_strcpy(q, p);
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
|
||||
IP_GLOBAL struct ifc *
|
||||
ifc_find(char *name)
|
||||
{
|
||||
struct ifc *ifcp;
|
||||
|
||||
for (ifcp = ipripng_ifhead(); ifcp; ifcp = ifcp->ifc_next) {
|
||||
if (ipcom_strcmp(name, ifcp->ifc_name) == 0)
|
||||
return ifcp;
|
||||
}
|
||||
return (struct ifc *)IP_NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
IP_GLOBAL struct iff *
|
||||
iff_find(struct ifc *ifcp, int type)
|
||||
{
|
||||
struct iff *iffp;
|
||||
|
||||
for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
|
||||
if (iffp->iff_type == type)
|
||||
return iffp;
|
||||
}
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
IP_GLOBAL void
|
||||
ifflags(int flags,
|
||||
char *ripng_if_buf)
|
||||
{
|
||||
|
||||
ipcom_strcpy(ripng_if_buf, "");
|
||||
|
||||
#define IFFLAG(s, f) \
|
||||
do { \
|
||||
if (flags & (f)) { \
|
||||
if (ripng_if_buf[0]) \
|
||||
ipcom_strcat(ripng_if_buf, ","); \
|
||||
ipcom_strcat(ripng_if_buf, s); \
|
||||
} \
|
||||
} while (0)
|
||||
IFFLAG("UP", IP_IFF_UP);
|
||||
#ifdef IP_IFF_INET_UP
|
||||
IFFLAG("INET_UP", IP_IFF_INET_UP);
|
||||
#endif
|
||||
#ifdef IP_IFF_INET6_UP
|
||||
IFFLAG("INET6_UP", IP_IFF_INET6_UP);
|
||||
#endif
|
||||
IFFLAG("BROADCAST", IP_IFF_BROADCAST);
|
||||
IFFLAG("DEBUG", IP_IFF_DEBUG);
|
||||
IFFLAG("LOOPBACK", IP_IFF_LOOPBACK);
|
||||
IFFLAG("POINTOPOINT", IP_IFF_POINTOPOINT);
|
||||
#ifdef IP_IFF_NOTRAILERS
|
||||
IFFLAG("NOTRAILERS", IP_IFF_NOTRAILERS);
|
||||
#endif
|
||||
#ifdef IP_IFF_SMART
|
||||
IFFLAG("SMART", IP_IFF_SMART);
|
||||
#endif
|
||||
IFFLAG("RUNNING", IP_IFF_RUNNING);
|
||||
IFFLAG("NOARP", IP_IFF_NOARP);
|
||||
IFFLAG("PROMISC", IP_IFF_PROMISC);
|
||||
IFFLAG("ALLMULTI", IP_IFF_ALLMULTI);
|
||||
IFFLAG("OACTIVE", IP_IFF_OACTIVE);
|
||||
IFFLAG("SIMPLEX", IP_IFF_SIMPLEX);
|
||||
IFFLAG("LINK0", IP_IFF_LINK0);
|
||||
IFFLAG("LINK1", IP_IFF_LINK1);
|
||||
IFFLAG("LINK2", IP_IFF_LINK2);
|
||||
IFFLAG("MULTICAST", IP_IFF_MULTICAST);
|
||||
#undef IFFLAG
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
IP_GLOBAL int
|
||||
mask2len(const struct in6_addr *addr, int lenlim)
|
||||
{
|
||||
int i = 0, j;
|
||||
const Ip_u8 *p = (Ip_u8 *)addr;
|
||||
|
||||
for (j = 0; j < lenlim; j++, p++) {
|
||||
if (*p != 0xff)
|
||||
break;
|
||||
i += 8;
|
||||
}
|
||||
if (j < lenlim) {
|
||||
switch (*p) {
|
||||
#define MASKLEN(m, l) case m: do { i += l; break; } while (0)
|
||||
MASKLEN(0xfe, 7); break;
|
||||
MASKLEN(0xfc, 6); break;
|
||||
MASKLEN(0xf8, 5); break;
|
||||
MASKLEN(0xf0, 4); break;
|
||||
MASKLEN(0xe0, 3); break;
|
||||
MASKLEN(0xc0, 2); break;
|
||||
MASKLEN(0x80, 1); break;
|
||||
#undef MASKLEN
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Returns a pointer to ifac whose address and prefix length matches
|
||||
* with the address and prefix length specified in the arguments.
|
||||
*/
|
||||
IP_GLOBAL struct ifac *
|
||||
ifa_match(const struct ifc *ifcp, const struct in6_addr *ia, int plen)
|
||||
{
|
||||
struct ifac *ifa;
|
||||
|
||||
for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
|
||||
if (IP_IN6_ARE_ADDR_EQUAL(&ifa->ifa_addr, (struct in6_addr *)ia) &&
|
||||
ifa->ifa_plen == plen)
|
||||
break;
|
||||
}
|
||||
return ifa;
|
||||
}
|
||||
|
||||
|
||||
|
||||
IP_GLOBAL int
|
||||
getifmtu(int ifindex)
|
||||
{
|
||||
int mib[6];
|
||||
char *buf;
|
||||
Ip_size_t msize;
|
||||
struct Ipnet_if_msghdr *ifm;
|
||||
int mtu;
|
||||
|
||||
mib[0] = IP_CTL_NET;
|
||||
mib[1] = IP_PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = IP_AF_INET6;
|
||||
mib[4] = IP_NET_RT_IFLIST;
|
||||
mib[5] = ifindex;
|
||||
if (ipcom_sysctl(mib, 6, IP_NULL, &msize, IP_NULL, 0) < 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "sysctl estimate NET_RT_IFLIST in getifmtu");
|
||||
return (-1);
|
||||
}
|
||||
if ((buf = (char *)ipcom_malloc(msize)) == IP_NULL)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "malloc failed in getifmtu");
|
||||
return (-1);
|
||||
}
|
||||
if (ipcom_sysctl(mib, 6, buf, &msize, IP_NULL, 0) < 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "sysctl NET_RT_IFLIST in getifmtu");
|
||||
ipcom_free (buf);
|
||||
return (-1);
|
||||
}
|
||||
ifm = (struct Ipnet_if_msghdr *)buf;
|
||||
mtu = (int)ifm->ifm_data.ifi_mtu;
|
||||
ipcom_free(buf);
|
||||
return mtu;
|
||||
}
|
||||
|
||||
|
||||
static const Ip_u8 plent[8] = {
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
|
||||
};
|
||||
|
||||
IP_GLOBAL void
|
||||
applyplen(struct in6_addr *ia, int plen)
|
||||
{
|
||||
Ip_u8 *p;
|
||||
int i;
|
||||
|
||||
p = ia->s6_addr;
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (plen <= 0)
|
||||
*p = 0;
|
||||
else if (plen < 8)
|
||||
*p &= plent[plen];
|
||||
p++, plen -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This function is required to add an offset to the time() call.
|
||||
* VxWorks returns time since bootup, but RIPng subtracts RIP_LIFETIME and
|
||||
* RIP_HOLDDOWN from this. If RIPng is started early after boot, then the
|
||||
* result of the subtraction is a negative number. Unfortunately time_t is an
|
||||
* unsigned long so the result is considered a high number in comparisons.
|
||||
*
|
||||
* The offset time returned from this ensures that time_t will never be
|
||||
* subtracted past zero.
|
||||
*
|
||||
* All calls to time() in this code are replaced by time_offset() calls.
|
||||
*/
|
||||
|
||||
IP_GLOBAL Ip_time_t time_offset(Ip_time_t *tod)
|
||||
{
|
||||
return (ipcom_time(tod) + RIP_LIFETIME + RIP_HOLDDOWN);
|
||||
}
|
||||
|
||||
|
||||
IP_GLOBAL Ip_time_t ipripng_nexttrigger_time()
|
||||
{
|
||||
Ip_time_t t;
|
||||
|
||||
long r = ipcom_random();
|
||||
t = (int)(RIP_TRIG_INT6_MIN +
|
||||
(RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / IP_RAND_MAX ));
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
IP_GLOBAL int
|
||||
sin6mask2len(const struct Ip_sockaddr_in6 *sin6)
|
||||
{
|
||||
|
||||
return mask2len(&sin6->sin6_addr,
|
||||
(int)(sin6->sin6_len - ip_offsetof(struct Ip_sockaddr_in6, sin6_addr)));
|
||||
}
|
||||
|
||||
|
||||
IP_GLOBAL void
|
||||
rtflags(struct Ipnet_rt_msghdr *rtm,
|
||||
char *ripng_rt_buf)
|
||||
{
|
||||
|
||||
/*
|
||||
* letter conflict should be okay. painful when *BSD diverges...
|
||||
*/
|
||||
ipcom_strcpy(ripng_rt_buf, "");
|
||||
|
||||
#define RTFLAG(s, f) \
|
||||
do { \
|
||||
if (rtm->rtm_flags & (f)) \
|
||||
ipcom_strcat(ripng_rt_buf, (s)); \
|
||||
} while (0)
|
||||
RTFLAG("U", IPNET_RTF_UP);
|
||||
RTFLAG("G", IPNET_RTF_GATEWAY);
|
||||
RTFLAG("H", IPNET_RTF_HOST);
|
||||
RTFLAG("R", IPNET_RTF_REJECT);
|
||||
RTFLAG("D", IPNET_RTF_DYNAMIC);
|
||||
RTFLAG("M", IPNET_RTF_MODIFIED);
|
||||
RTFLAG("d", IPNET_RTF_DONE);
|
||||
#ifdef IPNET_RTF_MASK
|
||||
RTFLAG("m", IPNET_RTF_MASK);
|
||||
#endif
|
||||
RTFLAG("C", IPNET_RTF_CLONING);
|
||||
#ifdef IPNET_RTF_CLONED
|
||||
RTFLAG("c", IPNET_RTF_CLONED);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_PRCLONING
|
||||
RTFLAG("c", IPNET_RTF_PRCLONING);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_WASCLONED
|
||||
RTFLAG("W", IPNET_RTF_WASCLONED);
|
||||
#endif
|
||||
RTFLAG("X", IPNET_RTF_XRESOLVE);
|
||||
RTFLAG("L", IPNET_RTF_LLINFO);
|
||||
RTFLAG("S", IPNET_RTF_STATIC);
|
||||
RTFLAG("B", IPNET_RTF_BLACKHOLE);
|
||||
#ifdef IPNET_RTF_PROTO3
|
||||
RTFLAG("3", IPNET_RTF_PROTO3);
|
||||
#endif
|
||||
RTFLAG("2", IPNET_RTF_PROTO2);
|
||||
RTFLAG("1", IPNET_RTF_PROTO1);
|
||||
#ifdef IPNET_RTF_BROADCAST
|
||||
RTFLAG("b", IPNET_RTF_BROADCAST);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_DEFAULT
|
||||
RTFLAG("d", IPNET_RTF_DEFAULT);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_ISAROUTER
|
||||
RTFLAG("r", IPNET_RTF_ISAROUTER);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_TUNNEL
|
||||
RTFLAG("T", IPNET_RTF_TUNNEL);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_AUTH
|
||||
RTFLAG("A", IPNET_RTF_AUTH);
|
||||
#endif
|
||||
#ifdef IPNET_RTF_CRYPT
|
||||
RTFLAG("E", IPNET_RTF_CRYPT);
|
||||
#endif
|
||||
#undef RTFLAG
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* outbound filter logic, per-route/interface.
|
||||
*/
|
||||
IP_PUBLIC int
|
||||
out_filter(Ipripng_rt *rrt, struct ifc *ifcp)
|
||||
{
|
||||
struct iff *iffp;
|
||||
struct in6_addr ia;
|
||||
int ok;
|
||||
|
||||
/*
|
||||
* -A: filter out less specific routes, if we have aggregated
|
||||
* route configured.
|
||||
*/
|
||||
for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
|
||||
if (iffp->iff_type != 'A')
|
||||
continue;
|
||||
if (rrt->rrt_info.rip6_plen <= iffp->iff_plen)
|
||||
continue;
|
||||
ia = rrt->rrt_info.rip6_dest;
|
||||
applyplen(&ia, iffp->iff_plen);
|
||||
if (IP_IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* if it is an aggregated route, advertise it only to the
|
||||
* interfaces specified on -A.
|
||||
*/
|
||||
if ((rrt->rrt_rflags & RRTF_AGGREGATE) != 0) {
|
||||
ok = 0;
|
||||
for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
|
||||
if (iffp->iff_type != 'A')
|
||||
continue;
|
||||
if (rrt->rrt_info.rip6_plen == iffp->iff_plen &&
|
||||
IP_IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest,
|
||||
&iffp->iff_addr)) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* -O: advertise only if prefix matches the configured prefix.
|
||||
*/
|
||||
if (iff_find(ifcp, 'O')) {
|
||||
ok = 0;
|
||||
for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
|
||||
if (iffp->iff_type != 'O')
|
||||
continue;
|
||||
if (rrt->rrt_info.rip6_plen < iffp->iff_plen)
|
||||
continue;
|
||||
ia = rrt->rrt_info.rip6_dest;
|
||||
applyplen(&ia, iffp->iff_plen);
|
||||
if (IP_IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr)) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the prefix should be advertised */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine if the route is to be advertised on the specified interface.
|
||||
* It checks options specified in the arguments and the split horizon rule.
|
||||
* Returns:
|
||||
* 0 - if the route shouldn't be advertised.
|
||||
* 1 - if route should be advertised.
|
||||
* 2 - if route should be advd with infinite hopcount (poison rev)
|
||||
*
|
||||
* RIPng-learned routes are advertised depending on -p/h/x/y/z settings
|
||||
* Static routes are advertised depending on the -s/S setting.
|
||||
* Interface routes are not advertised for poison reverse or split horizon.
|
||||
* They are only advertised if Split Horizon is disabled.
|
||||
*/
|
||||
IP_GLOBAL int
|
||||
tobeadv(Ipripng_rt *rrt, struct ifc *ifcp)
|
||||
{
|
||||
|
||||
/* Special care for static routes */
|
||||
if (rrt->rrt_flags & IPNET_RTF_STATIC) {
|
||||
/* XXX don't advertise reject/blackhole routes */
|
||||
if (rrt->rrt_flags & (IPNET_RTF_REJECT | IPNET_RTF_BLACKHOLE))
|
||||
return 0;
|
||||
|
||||
if (ipripng_Sflag()) /* Yes, advertise it anyway */
|
||||
return 1;
|
||||
if (ipripng_sflag() && rrt->rrt_index != ifcp->ifc_index)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Split Horizon & Poison Reverse Config for this interface */
|
||||
if (ifcp->ifc_horizcfg == IF_SPLITH && (rrt->rrt_index == ifcp->ifc_index))
|
||||
return 0;
|
||||
|
||||
if (ifcp->ifc_horizcfg == IF_POISON && (rrt->rrt_index == ifcp->ifc_index))
|
||||
{
|
||||
/* If RIPng-learned, send route with metric 16. Otherwise don't send */
|
||||
|
||||
if (rrt->rrt_rflags & RRTF_RIPNGLEARNED)
|
||||
return 2;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
IP_GLOBAL Ip_bool
|
||||
ipripng_neighbor_verify(struct in6_addr * nb_addr)
|
||||
{
|
||||
struct nb_list * plist = ipripng_nb_list_root();
|
||||
struct in6_addr noindex_addr;
|
||||
|
||||
while (plist)
|
||||
{
|
||||
struct in6_addr * incoming_addr;
|
||||
|
||||
/* If link-local take the interface index out of the address */
|
||||
|
||||
if (IP_IN6_IS_ADDR_LINK_LOCAL(nb_addr))
|
||||
{
|
||||
noindex_addr = *nb_addr;
|
||||
SET_IN6_LINKLOCAL_IFINDEX (noindex_addr, 0);
|
||||
incoming_addr = &noindex_addr;
|
||||
}
|
||||
else
|
||||
incoming_addr = nb_addr;
|
||||
|
||||
if (IP_IN6_ARE_ADDR_EQUAL(incoming_addr, &plist->nb_addr))
|
||||
return (IP_TRUE);
|
||||
|
||||
plist = plist->nb_next;
|
||||
}
|
||||
|
||||
/* None found */
|
||||
|
||||
return (IP_FALSE);
|
||||
}
|
||||
|
||||
|
||||
IP_STATIC const int pl2m[9] = {
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
|
||||
};
|
||||
|
||||
IP_GLOBAL struct in6_addr *
|
||||
plen2mask(int n)
|
||||
{
|
||||
static struct in6_addr ia;
|
||||
Ip_u8 *p;
|
||||
int i;
|
||||
|
||||
ipcom_memset(&ia, 0, sizeof(struct in6_addr));
|
||||
p = (Ip_u8 *)&ia;
|
||||
for (i = 0; i < 16; i++, p++, n -= 8) {
|
||||
if (n >= 8) {
|
||||
*p = 0xff;
|
||||
continue;
|
||||
}
|
||||
*p = (Ip_u8)pl2m[n];
|
||||
break;
|
||||
}
|
||||
return &ia;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* END OF FILE
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user