| /* |
| * 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 */ |