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

953 lines
31 KiB
C

/*
******************************************************************************
* INTERPEAK EXAMPLE SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: iprip_daemon.c,v $ $Revision: 1.25.2.1 $
* $Source: /home/interpeak/CVSRoot/iprip/src/iprip_daemon.c,v $
* $Author: hxie $
* $State: Exp $ $Locker: $
*
* Copyright 2000-2007 Interpeak AB (http://www.interpeak.se). All rights reserved.
* Design and implementation by Lennart Bang <lob@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "iprip_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_ipd.h>
#include <ipnet_config.h>
#include <ipnet.h>
#include <ipnet_routesock.h>
#include <ipnet_cmd.h>
#include "iprip.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
#ifndef IPNET
#error IPRIP_REQUIRES_IPNET
#endif
#define IPNET_IF_LOOPBACK_INDEX 1 /* The index of the loopback interface */
/* Syslog priority and facility. */
#if defined(_WRS_CONFIG_IPRIP_SYSLOG_PRIORITY)
#define IPCOM_SYSLOG_PRIORITY _WRS_CONFIG_IPRIP_SYSLOG_PRIORITY
#else
#define IPCOM_SYSLOG_PRIORITY IPCOM_SYSLOG_PRIO_DEFAULT
#endif
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPRIP
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
IP_EXTERN IP_CONST char *iprip_staticroute_config[];
IP_GLOBAL char *iprip_ifgetconf(const char *ifname);
IP_GLOBAL const char *iprip_ifgetconfopt(const char *confstr, char *option);
IP_GLOBAL Ip_err iprip_ifattach(const char *ifname, const char *confstr);
IP_GLOBAL Ip_err iprip_ifdetach(const char *ifname);
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC Ip_err iprip_write(Ip_fd udp_fd, void *cookie, Ip_u32 ipaddr_n, Ipcom_sock_addr *dest, void *buf, Ip_size_t len);
IP_STATIC Ip_err iprip_add_route_rtsock(void *cookie, Iprip_rt *rt);
IP_STATIC Ip_err iprip_delete_route_rtsock(void *cookie, Iprip_rt *rt);
IPCOM_PROCESS(ipripd);
IP_PUBLIC Ip_err iprip_create(void);
IP_PUBLIC Ip_err iprip_start(void);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
IP_STATIC char iprip_dstr[16];
#if IPRIP_SYSLOG_PRIORITY >= IPCOM_LOG_DEBUG2
IP_STATIC Ipcom_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 Ipcom_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
****************************************************************************
*/
/*
*===========================================================================
* iprip_rtmsg_print_addresses
*===========================================================================
* Description:
* Parameters:
* Returns:
*/
#if IPRIP_SYSLOG_PRIORITY >= IPCOM_LOG_DEBUG2
IP_STATIC void
iprip_rtmsg_print_addresses(int addrs, struct Ip_sockaddr *first)
{
struct Ip_sockaddr *addr_ptr;
int i;
char addr_str[40];
char buf[10];
addr_ptr = first;
for (i = 0; i < IPNET_RTAX_MAX; i++)
{
if (IP_BIT_ISSET(addrs, 1 << i))
{
if (ipcom_cmd_sockaddr_to_str(addr_ptr, IP_FALSE, IP_TRUE, addr_str, sizeof(addr_str)) == IP_NULL)
{
/* Invalid address */
IP_PANIC2();
continue;
}
IPCOM_LOG2(DEBUG2, " " "%-10s: %s",
ipcom_cmd_key_to_str(iprip_rta_map, i, buf, sizeof(buf)),
addr_str);
addr_ptr = (struct Ip_sockaddr *) ((Ip_u8*) addr_ptr + IPCOM_SA_LEN_GET(addr_ptr));
}
}
}
#endif
/*
*===========================================================================
* iprip_rtsock_adddel
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
iprip_rtsock_adddel(Ip_fd rt_fd, Iprip_rt *rt, Ip_bool add)
{
struct Ip_sockaddr_in *sockaddr;
Ip_ssize_t length;
struct rtmsg_buf_struct
{
struct Ipnet_rt_msghdr msghdr;
struct Ip_sockaddr_in sin[3];
} rtmsg_buf;
static Ip_u32 seq;
char iprip_dstr2[16];
char iprip_dstr3[16];
IPCOM_LOG6(DEBUG2,
" ++ %s_route(): %s"
"/%s, metric=%ld, flags=0x%x"
" -> %s.",
add ? "add" : "delete",
ipcom_inet_ntop(IP_AF_INET, &rt->ipaddr_n, iprip_dstr, 16),
ipcom_inet_ntop(IP_AF_INET, &rt->mask_n, iprip_dstr2, 16),
rt->metric, rt->flags,
ipcom_inet_ntop(IP_AF_INET, &rt->router_n, iprip_dstr3, 16));
(void)iprip_dstr2;
(void)iprip_dstr3;
ipcom_memset(&rtmsg_buf, 0, sizeof(struct rtmsg_buf_struct));
sockaddr = rtmsg_buf.sin;
rtmsg_buf.msghdr.rtm_msglen = sizeof(struct Ipnet_rt_msghdr);
rtmsg_buf.msghdr.rtm_version = IPNET_RTM_VERSION;
rtmsg_buf.msghdr.rtm_type = (Ip_u8)(add ? IPNET_RTM_ADD : IPNET_RTM_DELETE);
rtmsg_buf.msghdr.rtm_table = 0;
rtmsg_buf.msghdr.rtm_flags = IPNET_RTF_GATEWAY | IPNET_RTF_UP | IPNET_RTF_DONE | IPNET_RTF_DYNAMIC;
rtmsg_buf.msghdr.rtm_addrs = 0;
rtmsg_buf.msghdr.rtm_pid = ipcom_getpid();
rtmsg_buf.msghdr.rtm_seq = ++seq;
rtmsg_buf.msghdr.rtm_rmx.rmx_rtt = 0; /* not used. */
rtmsg_buf.msghdr.rtm_rmx.rmx_rttvar = 0; /* not used. */
rtmsg_buf.msghdr.rtm_rmx.rmx_mtu = 0; /* use interface mtu. */
rtmsg_buf.msghdr.rtm_rmx.rmx_hopcount = (Ip_u32)rt->metric;
rtmsg_buf.msghdr.rtm_rmx.rmx_expire = IPCOM_ADDR_INFINITE;
/* Add route destination. */
IPCOM_SA_LEN_SET(sockaddr, sizeof(struct Ip_sockaddr_in));
sockaddr->sin_family = IP_AF_INET;
sockaddr->sin_addr.s_addr = rt->ipaddr_n;
rtmsg_buf.msghdr.rtm_msglen = (Ip_u16)(rtmsg_buf.msghdr.rtm_msglen + sizeof(struct Ip_sockaddr_in));
rtmsg_buf.msghdr.rtm_addrs |= IPNET_RTA_DST;
sockaddr++;
/* Add gateway if non zero. */
if (rt->router_n != 0)
{
IPCOM_SA_LEN_SET(sockaddr, sizeof(struct Ip_sockaddr_in));
sockaddr->sin_family = IP_AF_INET;
sockaddr->sin_addr.s_addr = rt->router_n;
rtmsg_buf.msghdr.rtm_msglen = (Ip_u16)(rtmsg_buf.msghdr.rtm_msglen + sizeof(struct Ip_sockaddr_in));
rtmsg_buf.msghdr.rtm_addrs |= IPNET_RTA_GATEWAY;
sockaddr++;
}
/* Add mask if network (non-host) route. */
if (rt->mask_n != 0xffffffff)
{
IPCOM_SA_LEN_SET(sockaddr, sizeof(struct Ip_sockaddr_in));
sockaddr->sin_family = IP_AF_INET;
sockaddr->sin_addr.s_addr = rt->mask_n;
rtmsg_buf.msghdr.rtm_msglen = (Ip_u16)(rtmsg_buf.msghdr.rtm_msglen + sizeof(struct Ip_sockaddr_in));
rtmsg_buf.msghdr.rtm_addrs |= IPNET_RTA_NETMASK;
}
else
rtmsg_buf.msghdr.rtm_flags |= IPNET_RTF_HOST;
/* Add/delete the route with IPNET. */
length = ipcom_send(rt_fd, &rtmsg_buf, rtmsg_buf.msghdr.rtm_msglen, 0);
if (length != rtmsg_buf.msghdr.rtm_msglen)
{
IPCOM_LOG2(DEBUG2, "failed to add route %s, errno = %d",
iprip_routeinfo(rt), ipcom_errno);
return IPCOM_ERR_FAILED;
}
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* iprip_add_route_rtsock
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
iprip_add_route_rtsock(void *cookie, Iprip_rt *rt)
{
#if WRS_CONFIG_LP64
assert(((long)cookie & 0xffffffff00000000) == 0);
#endif
return iprip_rtsock_adddel((Ip_fd)(long)cookie, rt, IP_TRUE);
}
/*
*===========================================================================
* iprip_delete_route_rtsock
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
iprip_delete_route_rtsock(void *cookie, Iprip_rt *rt)
{
#if WRS_CONFIG_LP64
assert(((long)cookie & 0xffffffff00000000) == 0);
#endif
return iprip_rtsock_adddel((Ip_fd)(long)cookie, rt, IP_FALSE);
}
/*
*===========================================================================
* iprip_write
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
iprip_write(Ip_fd udp_fd, void *cookie, Ip_u32 ipaddr_n, Ipcom_sock_addr *dest, void *buf, Ip_size_t len)
{
struct Ip_sockaddr_in faddr;
(void)cookie;
/* RIP multicast address, must set outgoing interface index in socket. */
if (dest->ipaddr_n == IPRIP_MADDR) /* 224.0.0.9 */
{
struct Ip_in_addr inaddr;
inaddr.s_addr = ipaddr_n;
if (ipcom_setsockopt(udp_fd, IP_IPPROTO_IP, IP_IP_MULTICAST_IF, &inaddr, sizeof(Ip_socklen_t)) == IP_SOCKERR)
{
IP_PANIC2();
}
}
/* Copy over the destination address in a socket address structure. */
ipcom_memset(&faddr, 0, sizeof(faddr));
faddr.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&faddr, sizeof(struct Ip_sockaddr_in));
faddr.sin_addr.s_addr = dest->ipaddr_n;
faddr.sin_port = dest->port_n;
/* Use sendto() to transmit the UDP packet. */
if (ipcom_sendto(udp_fd, buf, (Ip_size_t)len, 0, (IP_CONST struct Ip_sockaddr *)&faddr, sizeof(faddr)) < 0)
{
Ip_socklen_t errlen;
int so_errno;
char ifname[IP_IFNAMSIZ];
errlen = sizeof(int);
IPCOM_LOG3(ERR, "iprip_write() :: failed to send RIP packet to %s on %s, errno = %d",
ipcom_inet_ntop(IP_AF_INET, &dest->ipaddr_n, iprip_dstr, 16),
ipcom_if_indextoname(dest->ifindex, ifname),
ipcom_errno);
/* Clear socket error */
(void)ipcom_getsockopt(udp_fd, IP_SOL_SOCKET, IP_SO_ERROR, &so_errno, &errlen);
return -1;
}
/* success. */
return 0;
}
/*
*===========================================================================
* ipripd
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IPCOM_PROCESS(ipripd)
{
Ip_err ret;
Iprip_open conf;
Ip_fd udp_fd;
Ip_fd rt_fd = IP_INVALID_SOCKET;
Ip_fd ipd_fd = IP_INVALID_SOCKET;
Ip_pid_t ipripd_pid;
struct Ip_sockaddr_in addr;
struct Ip_sockaddr *sap_dst;
struct Ip_sockaddr *sap_gateway;
struct Ip_sockaddr *sap_netmask;
struct Ip_sockaddr *sap_ifp;
struct Ip_sockaddr *sap_ifa;
Ip_u32 org_offset, cur_offset;
Ip_fd_set read_set;
int optval, num, max;
Ip_ssize_t length;
Ip_bool iprip_init_ok = IP_FALSE;
Ip_bool iprip_open_ok = IP_FALSE;
struct Ip_msghdr msghdr;
struct Ip_iovec iovec;
struct Ip_in_pktinfo *pktinfop;
struct Ip_if_nameindex *oifrs, *ifrs;
char *ripconf;
int addrs;
Iprip_route route;
char option[64];
union Membuf_union
{
struct Ip_cmsghdr cm;
struct Ipnet_rt_msghdr rtmsg;
struct Ipnet_if_msghdr ifmsg;
struct Ipnet_ifa_msghdr ifamsg;
char control[IP_CMSG_SPACE(sizeof(struct Ip_in_addr)) + IP_CMSG_SPACE(sizeof(struct Ip_in_pktinfo))];
struct rtmsg_buf_struct
{
struct Ipnet_rt_msghdr msghdr;
struct Ip_sockaddr_in sin[4];
} rtmsg_buf;
struct rtmsg2_buf_struct
{
struct Ipnet_rt_msghdr msghdr;
struct Ip_sockaddr_in dst[1];
struct Ip_sockaddr_dl gateway[1];
struct Ip_sockaddr_dl ifp[1];
struct Ip_sockaddr_in ifa[1];
} rtmsg2_buf;
struct rtmsg3_buf_struct
{
struct Ipnet_rt_msghdr msghdr;
struct Ip_sockaddr_in dst[1];
struct Ip_sockaddr_in gateway[1];
struct Ip_sockaddr_in netmask[1];
struct Ip_sockaddr_dl ifp[1];
struct Ip_sockaddr_in ifa[1];
Ip_u32 filler[2];
} rtmsg3_buf;
char offset[1];
} membuf;
#if IPRIP_SYSLOG_PRIORITY >= IPCOM_LOG_DEBUG2
Ip_time_t start;
char buf[10];
#endif
ipcom_proc_init();
IPCOM_LOG0(INFO, "ipripd :: starting");
#if IPRIP_SYSLOG_PRIORITY >= IPCOM_LOG_DEBUG2
start = ipcom_time(0);
#endif
ipripd_pid = ipcom_getpid();
pktinfop = (struct Ip_in_pktinfo *)(membuf.control + IP_CMSG_ALIGN(sizeof(struct Ip_cmsghdr)));
iovec.iov_base = IP_NULL;
/* Get RIP UDP socket. */
udp_fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
if (udp_fd == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipripd :: ipcom_socket(IP_SOCK_DGRAM) failed, errno = %d", ipcom_errno);
goto badout;
}
/* Enable receive interface index on UDP socket. */
optval = 1;
if (ipcom_setsockopt(udp_fd, IP_IPPROTO_IP, IP_IP_PKTINFO, (IP_CONST void *)&optval, sizeof(Ip_socklen_t)) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipripd :: ipcom_setsockopt(IP_IP_PKTINFO) failed, errno = %d", ipcom_errno);
goto badout;
}
/* Enable broadcasting on socket. */
#ifdef IP_SO_BROADCAST
optval = 1;
if (ipcom_setsockopt(udp_fd, IP_SOL_SOCKET, IP_SO_BROADCAST, (IP_CONST void *)&optval, sizeof(Ip_socklen_t)) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipripd :: ipcom_setsockopt(IP_SO_BROADCAST) failed, errno = %d", ipcom_errno);
goto badout;
}
#endif
/* Bind to RIP port. */
ipcom_memset(&addr, 0, sizeof(addr));
addr.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&addr, sizeof(struct Ip_sockaddr_in));
addr.sin_addr.s_addr = IP_INADDR_ANY;
addr.sin_port = ip_htons(520);
if (ipcom_bind(udp_fd, (struct Ip_sockaddr *)&addr, sizeof(addr)) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "ipripd :: ipcom_bind(520) failed, errno = %d", ipcom_errno);
goto badout;
}
/* Get routing socket. */
rt_fd = ipcom_socket(IP_AF_ROUTE, IP_SOCK_RAW, 0);
if (rt_fd == IP_INVALID_SOCKET)
{
IPCOM_LOG1(ERR, "ipripd :: ipcom_socket(IP_SOCK_RAW) failed, errno = %d", ipcom_errno);
goto badout;
}
iovec.iov_base = ipcom_malloc(1500);
if (iovec.iov_base == IP_NULL)
{
IP_PANIC2();
IPCOM_LOG0(ERR, "ipripd :: ipcom_malloc(1500) failed, out of memory");
goto badout;
}
/***** Initialize IPRIP. *****/
ret = iprip_init();
if (ret != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "ipripd :: iprip_init() failed, err = %ld", ret);
goto badout;
}
iprip_init_ok = IP_TRUE;
/***** Open and configure IPRIP. *****/
conf.udp_fd = udp_fd;
conf.cookie = (void *)(long)rt_fd;
conf.rip_write = iprip_write;
conf.add_route = iprip_add_route_rtsock;
conf.delete_route = iprip_delete_route_rtsock;
conf.conf[0] = IP_TAG_END;
ret = iprip_open(&conf);
if (ret != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "ipripd :: iprip_open() failed, err = %ld", ret);
goto badout;
}
iprip_open_ok = IP_TRUE;
/***** Start RIP on all external interfaces that are up. *****/
ifrs = ipcom_if_nameindex();
if (ifrs == IP_NULL)
{
IPCOM_LOG0(ERR, "ipripd :: ipcom_if_nameindex() failed");
goto badout;
}
for (oifrs = ifrs; ifrs && ifrs->if_name != IP_NULL; ifrs++)
{
/* Do not run RIP on loopback interface. */
if (ipcom_strcmp(ifrs->if_name, "lo0") == 0 || ipcom_strcmp(ifrs->if_name, "lo") == 0)
continue;
ripconf = iprip_ifgetconf(ifrs->if_name);
if (ripconf == IP_NULL || ipcom_strstr(ripconf, "ignore"))
continue;
ret = iprip_ifattach(ifrs->if_name, ripconf);
if (ret != IPCOM_SUCCESS) /*lint -e415 */
{
IPCOM_LOG2(ERR, "ipripd :: failed to attach RIP on %s : %s",
ifrs->if_name, ipcom_err_string(ret));
}
}
ipcom_if_freenameindex(oifrs);
/***** Add initial static RIP routes. *****/
for(num = 0; iprip_staticroute_config[num] != IP_NULL; num++)
{
const char *confstr;
ipcom_memset(&route, 0, sizeof(Iprip_route));
route.metric = 1;
IP_BIT_SET(route.flags, IPRIP_ROUTE_FLAG_STATIC);
for(confstr = iprip_staticroute_config[num];;)
{
confstr = iprip_ifgetconfopt(confstr, option);
if (confstr == IP_NULL)
break;
if (ipcom_strncmp(option, "dst=", 4) == 0)
route.ipaddr_n = (Ip_u32)ipcom_inet_addr(&option[4]);
else if (ipcom_strncmp(option, "mask=", 5) == 0)
route.mask_n = (Ip_u32)ipcom_inet_addr(&option[5]);
else if (ipcom_strncmp(option, "gw=", 3) == 0)
route.router_n = (Ip_u32)ipcom_inet_addr(&option[3]);
else if (ipcom_strncmp(option, "metric=", 7) == 0)
route.metric = ipcom_atoi(&option[7]);
}
if (iprip_rtadd(&route) == IPCOM_SUCCESS)
{
int i;
i = ipcom_sprintf(option, "%s",
ipcom_inet_ntop(IP_AF_INET, &route.ipaddr_n, iprip_dstr, 16));
i += ipcom_sprintf(option + i, "/%s",
ipcom_inet_ntop(IP_AF_INET, &route.mask_n, iprip_dstr, 16));
(void)ipcom_sprintf(option + i, " -> %s",
ipcom_inet_ntop(IP_AF_INET, &route.router_n, iprip_dstr, 16));
IPCOM_LOG1(INFO, "ipripd :: added static RIP route: %s", option);
}
}
/* IPD init. */
if (ipcom_ipd_init("iprip", IPCOM_SUCCESS, &ipd_fd) != IPCOM_SUCCESS)
goto badout;
/***** Input loop. *****/
max = IP_MAX(udp_fd, rt_fd);
max = IP_MAX(max, ipd_fd);
IP_FD_ZERO(&read_set);
for(;;)
{
input:
IP_FD_SET(udp_fd, &read_set);
IP_FD_SET(rt_fd, &read_set);
IP_FD_SET(ipd_fd, &read_set);
num = ipcom_socketselect(max + 1, &read_set, IP_NULL, IP_NULL, IP_NULL);
/* RIP input. */
if (num > 0 && IP_FD_ISSET(udp_fd, &read_set))
{
num--;
msghdr.msg_name = &addr;
msghdr.msg_namelen = sizeof(struct Ip_sockaddr_in);
iovec.iov_len = 1500;
msghdr.msg_iov = &iovec;
msghdr.msg_iovlen = 1;
msghdr.msg_control = membuf.control;
msghdr.msg_controllen = sizeof(membuf.control);
msghdr.msg_flags = 0;
length = ipcom_recvmsg(udp_fd, &msghdr, 0);
if (length > 0)
{
Ipcom_sock_packet sockpkt;
sockpkt.from.ipaddr_n = addr.sin_addr.s_addr;
sockpkt.from.ifindex = pktinfop->ipi_ifindex;
sockpkt.from.port_n = addr.sin_port;
sockpkt.buf = iovec.iov_base;
sockpkt.maxlen = 1500;
sockpkt.len = (Ip_size_t)length;
/* Pass packet to IPRIP for input parsing. */
ret = iprip_ifread((Ip_u32)pktinfop->ipi_ifindex, &sockpkt);
if (ret != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "ipripd :: iprip_ifread() failed, err = %ld", ret);
}
}
else if (length < 0)
{
int err;
Ip_socklen_t errlen = sizeof(int);
(void)ipcom_getsockopt(udp_fd, IP_SOL_SOCKET, IP_SO_ERROR, &err, &errlen);
}
}
/* Routing socket input. */
if (num > 0 && IP_FD_ISSET(rt_fd, &read_set))
{
num--;
length = ipcom_recv(rt_fd, (void *)&membuf.rtmsg_buf, sizeof(membuf), 0);
if (length < (Ip_ssize_t)sizeof(struct Ipnet_rt_msghdr))
{
IP_PANIC2();
continue;
}
/* Truncated. */
if (length < membuf.rtmsg.rtm_msglen)
{
if (membuf.rtmsg_buf.sin[0].sin_family == IP_AF_INET6)
continue;
IPCOM_LOG2(DEBUG, "ipripd :: truncated rtsock message %ld/%d", length, (int)membuf.rtmsg.rtm_msglen);
continue;
}
switch(membuf.rtmsg.rtm_type)
{
case IPNET_RTM_NEWADDR:
case IPNET_RTM_DELADDR:
/*
* org_offset = sizeof(struct Ipnet_ifa_msghdr);
* addrs = membuf.ifamsg.ifam_addrs;
*/
goto input;
case IPNET_RTM_IFINFO:
org_offset = sizeof(struct Ipnet_if_msghdr);
addrs = membuf.ifmsg.ifm_addrs;
break;
default:
/* Ignore our own route messages. */
if (membuf.rtmsg.rtm_pid == ipripd_pid)
goto input;
/* Ignore routes to loopback. */
if (membuf.rtmsg.rtm_index == IPNET_IF_LOOPBACK_INDEX)
goto input;
/* Ignore failed routes. */
if (membuf.rtmsg.rtm_errno != 0)
goto input;
org_offset = sizeof(struct Ipnet_rt_msghdr);
addrs = (int)membuf.rtmsg.rtm_addrs;
break;
}
cur_offset = org_offset;
sap_dst = sap_netmask = sap_ifa = (struct Ip_sockaddr *)IP_NULL;
/*sap_gateway = IP_NULL;*/
if (IP_BIT_ISSET(addrs, IPNET_RTA_DST))
{
sap_dst = (struct Ip_sockaddr *)&membuf.offset[cur_offset];
cur_offset += IPCOM_SA_LEN_GET(sap_dst);
/* Ignore all non IPv4 DST messages. */
if (sap_dst->sa_family != IP_AF_INET)
continue;
}
if (IP_BIT_ISSET(addrs, IPNET_RTA_GATEWAY))
{
sap_gateway = (struct Ip_sockaddr *)&membuf.offset[cur_offset];
cur_offset += IPCOM_SA_LEN_GET(sap_gateway);
}
if (IP_BIT_ISSET(addrs, IPNET_RTA_NETMASK))
{
sap_netmask = (struct Ip_sockaddr *)&membuf.offset[cur_offset];
cur_offset += IPCOM_SA_LEN_GET(sap_netmask);
}
if (IP_BIT_ISSET(addrs, IPNET_RTA_IFP))
{
sap_ifp = (struct Ip_sockaddr *)&membuf.offset[cur_offset];
cur_offset += IPCOM_SA_LEN_GET(sap_ifp);
}
if (IP_BIT_ISSET(addrs, IPNET_RTA_IFA))
{
sap_ifa = (struct Ip_sockaddr *)&membuf.offset[cur_offset];
/*cur_offset += sap_ifa->sa_len;*/
}
#if IPRIP_SYSLOG_PRIORITY >= IPCOM_LOG_DEBUG2
IPCOM_LOG4(DEBUG2, "ipripd :: [%ld] RTSOCK: %s, len: %d, %s",
ipcom_time(0) - start,
ipcom_cmd_key_to_str(iprip_rtm_map, membuf.rtmsg.rtm_type, buf, sizeof(buf)),
membuf.rtmsg.rtm_msglen,
membuf.rtmsg.rtm_type != IPNET_RTM_IFINFO ? "" :
IP_BIT_ISSET(membuf.ifmsg.ifm_flags, IP_IFF_UP) ? "UP" : "DOWN");
iprip_rtmsg_print_addresses(addrs, (struct Ip_sockaddr *)&membuf.offset[org_offset]);
#endif
switch(membuf.rtmsg.rtm_type)
{
case IPNET_RTM_ADD:
case IPNET_RTM_DELETE:
/* Prepare IPRIP route structure. */
ipcom_memset(&route, 0, sizeof(Iprip_route));
route.metric = (Ip_s32)membuf.rtmsg.rtm_rmx.rmx_hopcount;
IP_BIT_SET(route.flags, IPRIP_ROUTE_FLAG_LEAKED);
ip_assert(sap_dst != IP_NULL);
route.ipaddr_n = ((struct Ip_sockaddr_in *)sap_dst)->sin_addr.s_addr;
route.mask_n = sap_netmask ? ((struct Ip_sockaddr_in *)sap_netmask)->sin_addr.s_addr : 0xffffffff;
route.router_n = sap_ifa ? ((struct Ip_sockaddr_in *)sap_ifa)->sin_addr.s_addr : 0;
if (route.metric == 0)
{
route.metric = 1;
IPCOM_LOG1(DEBUG2, "ipripd :: adjusting 0 metric local leaked route: %s",
ipcom_inet_ntop(IP_AF_INET, &route.ipaddr_n, iprip_dstr, 16));
}
/* Add/delete leaked route. */
if (membuf.rtmsg.rtm_type == IPNET_RTM_ADD)
ret = iprip_rtadd(&route);
else
ret = iprip_rtdelete(&route);
if (ret == IPCOM_SUCCESS)
{
int i;
i = ipcom_sprintf(option, "%s",
ipcom_inet_ntop(IP_AF_INET, &route.ipaddr_n, iprip_dstr, 16));
i += ipcom_sprintf(option + i, "/%s",
ipcom_inet_ntop(IP_AF_INET, &route.mask_n, iprip_dstr, 16));
(void)ipcom_sprintf(option + i, " -> %s",
ipcom_inet_ntop(IP_AF_INET, &route.router_n, iprip_dstr, 16));
IPCOM_LOG2(DEBUG, "ipripd :: %s leaked RIP route: %s",
membuf.rtmsg.rtm_type == IPNET_RTM_ADD ? "added" : "deleted",
option);
}
break;
case IPNET_RTM_IFINFO:
{
char ifname[IP_IFNAMSIZ];
Ip_bool isopen;
if (ipcom_if_indextoname(membuf.ifmsg.ifm_index, ifname) == IP_NULL)
break;
isopen = iprip_ifisopen(membuf.ifmsg.ifm_index);
if (isopen)
{
if (IP_BIT_ISFALSE(membuf.ifmsg.ifm_flags, IP_IFF_UP))
{
if (iprip_ifdetach(ifname) != IPCOM_SUCCESS)
{
IPCOM_LOG1(ERR, "ipripd :: failed to detach RIP on %s", ifname);
}
}
}
else
{
if (IP_BIT_ISTRUE(membuf.ifmsg.ifm_flags, IP_IFF_UP))
{
ripconf = iprip_ifgetconf(ifname);
if (ripconf != IP_NULL)
{
ret = iprip_ifattach(ifname, ripconf);
if (ret != IPCOM_SUCCESS) /*lint -e415 */
{
IPCOM_LOG2(ERR, "ipripd :: failed to attach RIP on %s : %s",
ifname, ipcom_err_string(ret));
}
}
}
}
}
break;
default:
break;
}
}
/* IPD socket input. */
if (num > 0 && IP_FD_ISSET(ipd_fd, &read_set))
{
int event;
event = ipcom_ipd_input(ipd_fd);
switch(event)
{
case IPCOM_IPD_EVENT_RECONFIGURE:
IPCOM_LOG0(INFO, "received IPD reconfigure message");
iprip_config_read();
break;
case IPCOM_IPD_EVENT_KILL:
IPCOM_LOG0(INFO, "received IPD kill message");
goto badout;
default:
break;
}
}
}
badout:
if (ipd_fd == IP_INVALID_SOCKET)
(void)ipcom_ipd_init("iprip", IPCOM_ERR_FAILED, &ipd_fd);
if (iprip_open_ok)
(void)iprip_close();
if (iprip_init_ok)
(void)iprip_exit();
if (iovec.iov_base != IP_NULL)
ipcom_free(iovec.iov_base);
if (udp_fd != IP_INVALID_SOCKET)
ipcom_socketclose(udp_fd);
if (rt_fd != IP_INVALID_SOCKET)
ipcom_socketclose(rt_fd);
(void)ipcom_ipd_exit("iprip", ipd_fd);
IPCOM_LOG0(INFO, "ipripd :: ending");
ipcom_proc_exit();
}
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iprip_create
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprip_create(void)
{
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* iprip_start
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC Ip_err
iprip_start(void)
{
Ip_err ret;
Ipcom_proc_attr attr;
ipcom_proc_attr_init(&attr);
attr.priority = IPCOM_PRIORITY_DEFAULT - 1;
ret = ipcom_proc_acreate("ipripd", ipripd, &attr, IP_NULL);
ip_assert(ret == IPCOM_SUCCESS);
return ret;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/