/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "iprip_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 **************************************************************************** */