コード例 #1
0
ファイル: route_sysctl.cpp プロジェクト: duniansampa/SigLog
static int
_load_routing_table_from_sysctl(netsnmp_container* container, int *index,
    int family)
{
    char *buf, *lim, *next;
    int mib[6];
    size_t needed;
    int err;
    u_char dest_len, dest_type;
    struct rt_msghdr *rtm;

    buf = NULL;
    err = 0;

    if (family == AF_INET) {
        dest_len = 4;
        dest_type = INETADDRESSTYPE_IPV4;
    } else if (family == AF_INET6) {
        dest_len = 16;
        dest_type = INETADDRESSTYPE_IPV6;
    } else {
        err = EINVAL;
        goto out;
    }

    mib[0] = CTL_NET;
    mib[1] = PF_ROUTE;
    mib[2] = 0;
    mib[3] = family;
    mib[4] = NET_RT_DUMP;
    mib[5] = 0;

    if (sysctl(mib, (sizeof(mib) / sizeof(mib[0])), NULL, &needed, NULL,
        0) == -1) {
        err = errno;
        goto out;
    }

    if ((buf = malloc(needed)) == NULL) {
        err = ENOMEM;
        goto out;
    }

    if (sysctl(mib, (sizeof(mib) / sizeof(mib[0])), buf, &needed, NULL,
        0) == -1) {
        err = errno;
        goto out;
    }

    lim = buf + needed;

    for (next = buf; next < lim; next += rtm->rtm_msglen) {    
	struct sockaddr *if_name = NULL, *if_addr = NULL;
	struct sockaddr *dest_sa = NULL, *gateway_sa = NULL, *netmask_sa = NULL;
	netsnmp_route_entry *entry;
	char *addr_ptr;

        rtm = (struct rt_msghdr*)next;

        /* 
         * Some code in netstat checks for this ("netmasks done" case).
         * Filter this out (I don't know why it should exist).
         */
        if (rtm->rtm_addrs == RTA_DST)
            continue;

        entry = netsnmp_access_route_entry_create();
        if (entry == NULL)
            return -3;
        memset(entry->rt_dest, 0, dest_len);
        entry->rt_mask = 0;
        memset(entry->rt_nexthop, 0, dest_len);

        addr_ptr = (char *)(rtm + 1);

	if (rtm->rtm_addrs &  RTA_DST) {
	    dest_sa = (struct sockaddr *)addr_ptr;
	    addr_ptr += SA_SIZE(dest_sa);
	}
	if (rtm->rtm_addrs &  RTA_GATEWAY) {
	    gateway_sa = (struct sockaddr *)addr_ptr;
	    addr_ptr += SA_SIZE(gateway_sa);
	}
	if (rtm->rtm_addrs &  RTA_NETMASK) {
	    netmask_sa = (struct sockaddr *)addr_ptr;
	    addr_ptr += SA_SIZE(netmask_sa);
	}
	if (rtm->rtm_addrs &  RTA_IFP) {
	    if_name = (struct sockaddr *)addr_ptr;
	    addr_ptr += SA_SIZE(if_name);
	}
	if (rtm->rtm_addrs &  RTA_IFA) {
	    if_addr = (struct sockaddr *)addr_ptr;
	    addr_ptr += SA_SIZE(if_addr);
	}

        entry->if_index = rtm->rtm_index;

        /* arbitrary index */
        entry->ns_rt_index = ++(*index);

        /* copy dest & next hop */
        entry->rt_dest_type = dest_type;
        entry->rt_dest_len = dest_len;
        if (rtm->rtm_addrs & RTA_DST) {
            if (family == AF_INET)
                memcpy(entry->rt_dest,
                    &((struct sockaddr_in*)dest_sa)->sin_addr, dest_len);
#ifdef NETSNMP_ENABLE_IPV6
            if (family == AF_INET6)
                memcpy(entry->rt_dest,
                    &((struct sockaddr_in6*)dest_sa)->sin6_addr, dest_len);
#endif
        }

        entry->rt_nexthop_type = dest_type;
        entry->rt_nexthop_len = dest_len;
        if (rtm->rtm_addrs & RTA_GATEWAY) {
            if (family == AF_INET)
                memcpy(entry->rt_nexthop,
                    &((struct sockaddr_in*)gateway_sa)->sin_addr, dest_len);
#ifdef NETSNMP_ENABLE_IPV6
            if (family == AF_INET6)
                memcpy(entry->rt_nexthop,
                    &((struct sockaddr_in6*)gateway_sa)->sin6_addr, dest_len);
#endif
        }
        else {
            if (family == AF_INET)
                memcpy(entry->rt_nexthop,
                    &((struct sockaddr_in*)if_addr)->sin_addr, dest_len);
#ifdef NETSNMP_ENABLE_IPV6
            if (family == AF_INET6)
                memcpy(entry->rt_nexthop,
                    &((struct sockaddr_in6*)if_addr)->sin6_addr, dest_len);
#endif
        }

        if (family == AF_INET) {
	    if (netmask_sa) {
            /* count bits in mask */
		entry->rt_pfx_len = netsnmp_ipaddress_ipv4_prefix_len(
			((struct sockaddr_in *)netmask_sa)->sin_addr.s_addr);
		memcpy(&entry->rt_mask, &((struct sockaddr_in *)netmask_sa)->sin_addr, 4);
	    }
	    else {
		entry->rt_pfx_len = 32;
	    }
        }
#ifdef NETSNMP_ENABLE_IPV6
        if (family == AF_INET6) {
	    if (netmask_sa) {
            /* count bits in mask */
		entry->rt_pfx_len = netsnmp_ipaddress_ipv6_prefix_len(
			((struct sockaddr_in6 *)netmask_sa)->sin6_addr);
		memcpy(&entry->rt_mask, &((struct sockaddr_in6 *)netmask_sa)->sin6_addr, 16);
	    }
	    else {
		entry->rt_pfx_len = 128;
	    }
        }
#endif

#ifdef USING_IP_FORWARD_MIB_INETCIDRROUTETABLE_INETCIDRROUTETABLE_MODULE
        /*
    inetCidrRoutePolicy OBJECT-TYPE 
        SYNTAX     OBJECT IDENTIFIER 
        MAX-ACCESS not-accessible 
        STATUS     current 
        DESCRIPTION 
               "This object is an opaque object without any defined 
                semantics.  Its purpose is to serve as an additional 
                index which may delineate between multiple entries to 
                the same destination.  The value { 0 0 } shall be used 
                as the default value for this object."
        */
	entry->rt_policy = calloc(3, sizeof(oid));
	entry->rt_policy[2] = entry->if_index;
	entry->rt_policy_len = sizeof(oid)*3;
#endif

        entry->rt_type = _type_from_flags(rtm->rtm_flags);
	entry->rt_age = rtm->rtm_rmx.rmx_expire;
	entry->rt_nexthop_as = 0;
	/* entry->rt_metric1 = rtm->rtm_rmx.rmx_hopcount; */

        if (rtm->rtm_flags & RTF_DYNAMIC)
            entry->rt_proto = IANAIPROUTEPROTOCOL_ICMP;
        else if (rtm->rtm_flags & RTF_STATIC)
            entry->rt_proto = IANAIPROUTEPROTOCOL_NETMGMT;
#ifdef RTF_LOCAL
        else if (rtm->rtm_flags & RTF_LOCAL)
            entry->rt_proto = IANAIPROUTEPROTOCOL_LOCAL;
#endif
        else
            entry->rt_proto = IANAIPROUTEPROTOCOL_OTHER;

        if (CONTAINER_INSERT(container, entry) < 0) {
            DEBUGMSGTL(("access:route:container",
                "error with route_entry: insert into container failed.\n"));
            netsnmp_access_route_entry_free(entry);
            continue;
        }
    }

out:
    free(buf);

    return err;
}
コード例 #2
0
ファイル: route_linux.c プロジェクト: adomaxbd/net-snmp
static int
_load_ipv4(netsnmp_container* container, u_long *index )
{
    FILE           *in;
    char            line[256];
    netsnmp_route_entry *entry = NULL;
    char            name[16];
    int             fd;

    DEBUGMSGTL(("access:route:container",
                "route_container_arch_load ipv4\n"));

    netsnmp_assert(NULL != container);

    /*
     * fetch routes from the proc file-system:
     */
    if (!(in = fopen("/proc/net/route", "r"))) {
        NETSNMP_LOGONCE((LOG_ERR, "cannot open /proc/net/route\n"));
        return -2;
    }

    /*
     * create socket for ioctls (see NOTE[1], below)
     */
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0) {
        snmp_log(LOG_ERR, "could not create socket\n");
        fclose(in);
        return -2;
    }

    fgets(line, sizeof(line), in); /* skip header */

    while (fgets(line, sizeof(line), in)) {
        char            rtent_name[32];
        int             refcnt, rc;
        uint32_t        dest, nexthop, mask;
        unsigned        flags, use;

        entry = netsnmp_access_route_entry_create();

        /*
         * as with 1.99.14:
         *    Iface Dest     GW       Flags RefCnt Use Met Mask     MTU  Win IRTT
         * BE eth0  00000000 C0A80101 0003  0      0   0   FFFFFFFF 1500 0   0 
         * LE eth0  00000000 0101A8C0 0003  0      0   0   00FFFFFF    0 0   0  
         */
        rc = sscanf(line, "%s %x %x %x %d %u %d %x %*d %*d %*d\n",
                    rtent_name, &dest, &nexthop,
                    /*
                     * XXX: fix type of the args 
                     */
                    &flags, &refcnt, &use, &entry->rt_metric1,
                    &mask);
        DEBUGMSGTL(("9:access:route:container", "line |%s|\n", line));
        if (8 != rc) {
            snmp_log(LOG_ERR,
                     "/proc/net/route data format error (%d!=8), line ==|%s|",
                     rc, line);
            
            netsnmp_access_route_entry_free(entry);        
            continue;
        }

        /*
         * temporary null terminated name
         */
        strlcpy(name, rtent_name, sizeof(name));

        /*
         * don't bother to try and get the ifindex for routes with
         * no interface name.
         * NOTE[1]: normally we'd use netsnmp_access_interface_index_find,
         * but since that will open/close a socket, and we might
         * have a lot of routes, call the ioctl routine directly.
         */
        if ('*' != name[0])
            entry->if_index =
                netsnmp_access_interface_ioctl_ifindex_get(fd,name);

        /*
         * arbitrary index
         */
        entry->ns_rt_index = ++(*index);

#ifdef USING_IP_FORWARD_MIB_IPCIDRROUTETABLE_IPCIDRROUTETABLE_MODULE
        memcpy(&entry->rt_mask, &mask, 4);
        /** entry->rt_tos = XXX; */
        /** rt info ?? */
#endif
        /*
         * copy dest & next hop
         */
        entry->rt_dest_type = INETADDRESSTYPE_IPV4;
        entry->rt_dest_len = 4;
        memcpy(entry->rt_dest, &dest, 4);

        entry->rt_nexthop_type = INETADDRESSTYPE_IPV4;
        entry->rt_nexthop_len = 4;
        memcpy(entry->rt_nexthop, &nexthop, 4);

        /*
         * count bits in mask
         */
        mask = htonl(mask);
        entry->rt_pfx_len = netsnmp_ipaddress_ipv4_prefix_len(mask);

#ifdef USING_IP_FORWARD_MIB_INETCIDRROUTETABLE_INETCIDRROUTETABLE_MODULE
        /*
    inetCidrRoutePolicy OBJECT-TYPE 
        SYNTAX     OBJECT IDENTIFIER 
        MAX-ACCESS not-accessible 
        STATUS     current 
        DESCRIPTION 
               "This object is an opaque object without any defined 
                semantics.  Its purpose is to serve as an additional 
                index which may delineate between multiple entries to 
                the same destination.  The value { 0 0 } shall be used 
                as the default value for this object."
        */
        /*
         * on linux, default routes all look alike, and would have the same
         * indexed based on dest and next hop. So we use the if index
         * as the policy, to distinguise between them. Hopefully this is
         * unique.
         * xxx-rks: It should really only be for the duplicate case, but that
         *     would be more complicated than I want to get into now. Fix later.
         */
        if (0 == nexthop) {
            entry->rt_policy = calloc(3, sizeof(oid));
            entry->rt_policy[2] = entry->if_index;
            entry->rt_policy_len = sizeof(oid)*3;
        }
#endif

        /*
         * get protocol and type from flags
         */
        entry->rt_type = _type_from_flags(flags);
        
        entry->rt_proto = (flags & RTF_DYNAMIC)
            ? IANAIPROUTEPROTOCOL_ICMP : IANAIPROUTEPROTOCOL_LOCAL;

        /*
         * insert into container
         */
        if (CONTAINER_INSERT(container, entry) < 0)
        {
            DEBUGMSGTL(("access:route:container", "error with route_entry: insert into container failed.\n"));
            netsnmp_access_route_entry_free(entry);
            continue;
        }
    }

    fclose(in);
    close(fd);
    return 0;
}
コード例 #3
0
ファイル: ipaddress_sysctl.c プロジェクト: fenner/net-snmp
/**
 *
 * @retval  0 no errors
 * @retval !0 errors
 */
int
netsnmp_arch_ipaddress_container_load(netsnmp_container *container,
                                      u_int load_flags)
{
    netsnmp_ipaddress_entry *entry = NULL;
    u_char *if_list = NULL, *cp;
    size_t if_list_size = 0;
    int sysctl_oid[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
    struct ifa_msghdr *ifa;
    struct sockaddr *a;
    int amask;
    int rc = 0;
    int idx_offset = 0;

    DEBUGMSGTL(("access:ipaddress:container:sysctl",
                "load (flags %u)\n", load_flags));

    if (NULL == container) {
        snmp_log(LOG_ERR, "no container specified/found for interface\n");
        return -1;
    }

    if (sysctl(sysctl_oid, sizeof(sysctl_oid)/sizeof(int), 0,
               &if_list_size, 0, 0) == -1) {
        snmp_log(LOG_ERR, "could not get interface info (size)\n");
        return -2;
    }

    if_list = (u_char*)malloc(if_list_size);
    if (if_list == NULL) {
        snmp_log(LOG_ERR, "could not allocate memory for interface info "
                 "(%u bytes)\n", (unsigned) if_list_size);
        return -3;
    } else {
        DEBUGMSGTL(("access:ipaddress:container:sysctl",
                    "allocated %u bytes for if_list\n",
                    (unsigned) if_list_size));
    }

    if (sysctl(sysctl_oid, sizeof(sysctl_oid)/sizeof(int), if_list,
               &if_list_size, 0, 0) == -1) {
        snmp_log(LOG_ERR, "could not get interface info\n");
        free(if_list);
        return -2;
    }

    /* pass 2: walk addresses */
    for (cp = if_list; cp < if_list + if_list_size; cp += ifa->ifam_msglen) {
        ifa = (struct ifa_msghdr *) cp;
        int rtax;

        if (ifa->ifam_type != RTM_NEWADDR)
            continue;

        DEBUGMSGTL(("access:ipaddress:container:sysctl",
                    "received 0x%x in RTM_NEWADDR for ifindex %u\n",
                    ifa->ifam_addrs, ifa->ifam_index));

        entry = netsnmp_access_ipaddress_entry_create();
        if (entry == NULL) {
            rc = -3;
            break;
        }

        a = (struct sockaddr *) (ifa + 1);
        entry->ia_status = IPADDRESSSTATUSTC_UNKNOWN;
        entry->ia_origin = IPADDRESSORIGINTC_OTHER;
	entry->ia_address_len = 0;
        for (amask = ifa->ifam_addrs, rtax = 0; amask != 0; amask >>= 1, rtax++) {
            if ((amask & 1) != 0) {
                entry->ns_ia_index = ++idx_offset;
                entry->if_index = ifa->ifam_index;
                DEBUGMSGTL(("access:ipaddress:container:sysctl",
                            "%d: a=%p, sa_len=%d, sa_family=0x%x\n",
                            (int)entry->if_index, a, a->sa_len, a->sa_family));

                if (a->sa_family == AF_INET || a->sa_family == 0) {
                    struct sockaddr_in *a4 = (struct sockaddr_in *)a;
		    char str[128];
		    DEBUGMSGTL(("access:ipaddress:container:sysctl",
		                "IPv4 addr %s\n", inet_ntop(AF_INET, &a4->sin_addr.s_addr, str, 128)));
                    if (rtax == RTAX_IFA) {
			entry->ia_address_len = 4;
                        memcpy(entry->ia_address, &a4->sin_addr.s_addr, entry->ia_address_len);
		    }
                    else if (rtax == RTAX_NETMASK)
                        entry->ia_prefix_len = netsnmp_ipaddress_ipv4_prefix_len(a4->sin_addr.s_addr);
                }
                else if (a->sa_family == AF_INET6) {
                    struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)a;
		    char str[128];
		    DEBUGMSGTL(("access:ipaddress:container:sysctl",
		                "IPv6 addr %s\n", inet_ntop(AF_INET6, &a6->sin6_addr.s6_addr, str, 128)));
                    if (rtax == RTAX_IFA) {
			entry->ia_address_len = 16;
                        memcpy(entry->ia_address, &a6->sin6_addr, entry->ia_address_len);
		    }
                    else if (rtax == RTAX_NETMASK) {
                        entry->ia_prefix_len = netsnmp_ipaddress_ipv6_prefix_len(a6->sin6_addr);
			DEBUGMSGTL(("access:ipaddress:container:sysctl",
			            "prefix_len=%d\n", entry->ia_prefix_len));
		    }
                }
                a = (struct sockaddr *) ( ((char *) a) + ROUNDUP(a->sa_len) );
            }
        }
	if (entry->ia_address_len == 0) {
	    DEBUGMSGTL(("access:ipaddress:container:sysctl",
	                "entry skipped\n"));
	    netsnmp_access_ipaddress_entry_free(entry);
	}
	else if (CONTAINER_INSERT(container, entry) < 0) {
            DEBUGMSGTL(("access:ipaddress:container","error with ipaddress_entry: insert into container failed.\n"));
            netsnmp_access_ipaddress_entry_free(entry);
            continue;
        }
    }

    if (if_list != NULL)
        free(if_list);

    return 0;
}