original files of m241
This commit is contained in:
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
* 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
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user