blob: ff8916184be98a1284f2def07de6844e593ebcb2 [file] [log] [blame]
/*
* Portions of this file are subject to copyright(s). See the Net-SNMP's
* COPYING file for more details and other copyrights that may apply.
*/
#include <net-snmp/net-snmp-config.h>
#include <sys/types.h>
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if HAVE_SYS_MBUF_H
#include <sys/mbuf.h>
#endif
#if HAVE_SYS_STREAM_H
#include <sys/stream.h>
#endif
#if HAVE_NET_ROUTE_H
#include <net/route.h>
#endif
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#if HAVE_NETDB_H
#include <netdb.h>
#endif
#include <errno.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <ctype.h>
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/data_access/ipaddress.h>
#include <net-snmp/data_access/route.h>
#include "ip-forward-mib/inetCidrRouteTable/inetCidrRouteTable.h"
#include "route_ioctl.h"
#ifdef cygwin
#include <windows.h>
#endif
#ifndef HAVE_STRUCT_RTENTRY_RT_DST
# define rt_dst rt_nodes->rn_key
#endif
#ifndef HAVE_STRUCT_RTENTRY_RT_HASH
# define rt_hash rt_pad1
#endif
#ifdef linux
# define NETSNMP_ROUTE_WRITE_PROTOCOL PF_ROUTE
#else
# define NETSNMP_ROUTE_WRITE_PROTOCOL 0
#endif
#ifdef irix6
#define SIOCADDRT SIOCADDMULTI
#define SIOCDELRT SIOCDELMULTI
#endif
#if defined SIOCADDRT && !defined(irix6)
int _netsnmp_ioctl_route_set_v4(netsnmp_route_entry * entry)
{
struct sockaddr_in dst, gateway, mask;
int s, rc;
RTENTRY route;
char * DEBUGSTR;
netsnmp_assert(NULL != entry); /* checked in netsnmp_arch_route_create */
netsnmp_assert((4 == entry->rt_dest_len) && (4 == entry->rt_nexthop_len));
s = socket(AF_INET, SOCK_RAW, NETSNMP_ROUTE_WRITE_PROTOCOL);
if (s < 0) {
snmp_log_perror("netsnmp_ioctl_route_set_v4: socket");
return -3;
}
memset(&route, 0, sizeof(route));
dst.sin_family = AF_INET;
memcpy(&dst.sin_addr.s_addr, entry->rt_dest, 4);
DEBUGSTR = inet_ntoa(dst.sin_addr);
DEBUGMSGTL(("access:route","add route to %s\n", DEBUGSTR));
gateway.sin_family = AF_INET;
memcpy(&gateway.sin_addr.s_addr, entry->rt_nexthop, 4);
DEBUGSTR = inet_ntoa(gateway.sin_addr);
DEBUGMSGTL(("access:route"," via %s\n", DEBUGSTR));
mask.sin_family = AF_INET;
if (entry->rt_pfx_len != 0)
mask.sin_addr.s_addr = netsnmp_ipaddress_ipv4_mask(entry->rt_pfx_len);
else
mask.sin_addr.s_addr = entry->rt_mask;
DEBUGSTR = inet_ntoa(mask.sin_addr);
DEBUGMSGTL(("access:route"," mask %s\n", DEBUGSTR));
memcpy(&route.rt_dst, &dst, sizeof(struct sockaddr_in));
memcpy(&route.rt_gateway, &gateway, sizeof(struct sockaddr_in));
memcpy(&route.rt_genmask, &mask, sizeof(struct sockaddr_in));
if (32 == entry->rt_pfx_len)
route.rt_flags |= RTF_HOST;
if (INETCIDRROUTETYPE_REMOTE == entry->rt_type)
route.rt_flags |= RTF_GATEWAY;
route.rt_flags |= RTF_UP;
#ifndef RTENTRY_4_4
route.rt_hash = entry->if_index;
#endif
rc = ioctl(s, SIOCADDRT, (caddr_t) & route);
if (rc < 0) {
snmp_log_perror("netsnmp_ioctl_route_set_v4: ioctl");
rc = -4;
}
close(s);
return rc;
}
#endif
#if defined SIOCDELRT && !defined(irix6)
int _netsnmp_ioctl_route_delete_v4(netsnmp_route_entry * entry)
{
struct sockaddr_in dst, mask;
struct sockaddr_in gateway;
int s, rc;
RTENTRY route;
char *DEBUGSTR;
netsnmp_assert(NULL != entry); /* checked in netsnmp_arch_route_delete */
netsnmp_assert((4 == entry->rt_dest_len) && (4 == entry->rt_nexthop_len));
s = socket(AF_INET, SOCK_RAW, NETSNMP_ROUTE_WRITE_PROTOCOL);
if (s < 0) {
snmp_log_perror("netsnmp_ioctl_route_delete_v4: socket");
return -3;
}
memset(&route, 0, sizeof(route));
dst.sin_family = AF_INET;
memcpy(&dst.sin_addr.s_addr, entry->rt_dest, 4);
DEBUGSTR = inet_ntoa(dst.sin_addr);
DEBUGMSGTL(("access:route","del route to %s\n", DEBUGSTR));
mask.sin_family = AF_INET;
if (entry->rt_pfx_len != 0)
mask.sin_addr.s_addr = netsnmp_ipaddress_ipv4_mask(entry->rt_pfx_len);
else
mask.sin_addr.s_addr = entry->rt_mask;
gateway.sin_family = AF_INET;
memcpy(&gateway.sin_addr.s_addr, entry->rt_nexthop, 4);
memcpy(&route.rt_dst, &dst, sizeof(struct sockaddr_in));
memcpy(&route.rt_genmask, &mask, sizeof(struct sockaddr_in));
memcpy(&route.rt_gateway, &gateway, sizeof(struct sockaddr_in));
if (32 == entry->rt_pfx_len)
route.rt_flags |= RTF_HOST;
if (INETCIDRROUTETYPE_REMOTE == entry->rt_type)
route.rt_flags |= RTF_GATEWAY;
route.rt_flags |= RTF_UP;
#ifndef RTENTRY_4_4
route.rt_hash = entry->if_index;
#endif
rc = ioctl(s, SIOCDELRT, (caddr_t) & route);
if (rc < 0) {
snmp_log_perror("netsnmp_ioctl_route_delete_v4: ioctl");
rc = -4;
}
close(s);
return rc;
}
#endif /* SIOCDELRT */