original files of m241

This commit is contained in:
neelimap
2026-07-30 11:19:44 +05:30
parent 170c2b3f3a
commit afc7070c1f
12254 changed files with 7655111 additions and 0 deletions
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
****************************************************************************
*/