Ejemplo n.º 1
0
	const std::list<vaddress> NetLinkManager::getAddressList(const vinterface &interface, const vaddress::Family f)
	{
		ibrcommon::MutexLock l(_call_mutex);

		if (_refresh_cache)
		{
			nl_cache_free(_addr_cache);
			nl_cache_free(_link_cache);

			_link_cache = rtnl_link_alloc_cache(_handle);

			if (_link_cache == NULL)
			{
				throw ibrcommon::vsocket_exception("netlink cache allocation failed");
			}

			_addr_cache = rtnl_addr_alloc_cache(_handle);

			if (_addr_cache == NULL)
			{
				nl_cache_free(_link_cache);
				throw ibrcommon::vsocket_exception("netlink cache allocation failed");
			}

			// mark the cache as refreshed
			_refresh_cache = false;
		}

		std::list<vaddress> addresses;

		struct rtnl_addr *filter = rtnl_addr_alloc();
		const std::string i = interface.toString();
		rtnl_addr_set_ifindex(filter, rtnl_link_name2i(_link_cache, i.c_str()));

		if (f == vaddress::VADDRESS_UNSPEC)
		{
			rtnl_addr_set_family(filter, AF_INET6);
			nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
									add_addr_to_list, &addresses);

			rtnl_addr_set_family(filter, AF_INET);
			nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
									add_addr_to_list, &addresses);
		}
		else
		{
			rtnl_addr_set_family(filter, f);
			nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
									add_addr_to_list, &addresses);
		}

		rtnl_addr_put(filter);

		return addresses;
	}
Ejemplo n.º 2
0
/*
 * Get the first AF_INET address on 'link'. Returns 0 if successful. Caller
 * must release reference to *addr.
 */
static int get_link_inet_addr(struct nl_sock *sk, struct rtnl_link *link,
        struct nl_addr **addr)
{
    struct nl_cache *addr_cache;
    int err;
    err = rtnl_addr_alloc_cache(sk, &addr_cache);
    if (err < 0) {
        warnx("rtnl_addr_alloc_cache() failed: %s", nl_geterror(err));
        return 1;
    }

    /* Retrieve the first AF_INET address on the requested interface. */
    struct rtnl_addr *filter;
    filter = rtnl_addr_alloc();
    assert(filter);
    rtnl_addr_set_ifindex(filter, rtnl_link_get_ifindex(link));
    rtnl_addr_set_family(filter, AF_INET);

    *addr = NULL;
    nl_cache_foreach_filter(addr_cache, (struct nl_object *)filter,
            match_first_addr, addr);
    if (*addr == NULL) {
        warnx("No AF_INET address found on veth");
        
        rtnl_addr_put(filter);
        nl_cache_free(addr_cache);
        return 1;
    }

    rtnl_addr_put(filter);
    nl_cache_free(addr_cache);
    return 0;
}
Ejemplo n.º 3
0
TError TNlLink::AddAddress(const TNlAddr &addr) {
    struct rtnl_addr *a = rtnl_addr_alloc();
    if (!a)
        return TError(EError::Unknown, "Cannot allocate address");

    rtnl_addr_set_link(a, Link);
    rtnl_addr_set_family(a, nl_addr_get_family(addr.Addr));
    rtnl_addr_set_flags(a, IFA_F_NODAD);

    int ret = rtnl_addr_set_local(a, addr.Addr);
    if (ret < 0) {
        rtnl_addr_put(a);
        return Error(ret, "Cannot set local address");
    }

    ret = rtnl_addr_add(GetSock(), a, 0);
    if (ret < 0) {
        rtnl_addr_put(a);
        return Error(ret, "Cannot add address");
    }

    rtnl_addr_put(a);

    return TError::Success();
}
Ejemplo n.º 4
0
int sysnet_interface_set_addr(VPNInterface *i)
{
    int err;

    struct nl_cache *link_cache;
    struct nl_sock *sock;
    struct rtnl_addr *addr;
    struct rtnl_link *link;
    struct nl_addr *local_addr;

    sock = nl_socket_alloc();
    nl_connect(sock, NETLINK_ROUTE);

    rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache);

    addr = rtnl_addr_alloc();
    link = rtnl_link_get_by_name(link_cache, i->name);
    local_addr = nl_addr_build(i->address.ip.family, &i->address.ip.ip4, sizeof(i->address.ip.ip4));

    rtnl_addr_set_local(addr, local_addr);
    rtnl_addr_set_family(addr, i->address.ip.family);
    rtnl_addr_set_prefixlen(addr, i->address.prefix);
    rtnl_addr_set_link(addr, link);

    if ((err = rtnl_addr_add(sock, addr, 0)) < 0) {
        tox_trace(i->context->tox, "Unable to add address %s on %s: %s", ip_ntoa(&i->address.ip), rtnl_link_get_name(link), nl_geterror(err));
    }
    else {
        tox_trace(i->context->tox, "Added address %s on \"%s\"", ip_ntoa(&i->address.ip), i->name);
    }

    rtnl_link_put(link);
    rtnl_addr_put(addr);
    nl_cache_free(link_cache);
    nl_addr_put(local_addr);
    nl_socket_free(sock);

    return err;
}
Ejemplo n.º 5
0
int main(int argc, char *argv[])
{
    char *unikernel;
    enum {
        QEMU,
        KVM,
        UKVM,
        UNIX
    } hypervisor;

    if (argc < 3) {
        fprintf(stderr, "usage: runner HYPERVISOR UNIKERNEL [ ARGS... ]\n");
        fprintf(stderr, "HYPERVISOR: qemu | kvm | ukvm | unix\n");
        return 1;
    }
    if (strcmp(argv[1], "qemu") == 0)
        hypervisor = QEMU;
    else if (strcmp(argv[1], "kvm") == 0)
        hypervisor = KVM;
    else if (strcmp(argv[1], "ukvm") == 0)
        hypervisor = UKVM;
    else if (strcmp(argv[1], "unix") == 0)
        hypervisor = UNIX;
    else {
        warnx("error: Invalid hypervisor: %s", argv[1]);
        return 1;
    }
    unikernel = argv[2];
    /*
     * Remaining arguments are to be passed on to the unikernel.
     */
    argv += 3;
    argc -= 3;

    /*
     * Check we have CAP_NET_ADMIN.
     */
    if (capng_get_caps_process() != 0) {
        warnx("error: capng_get_caps_process() failed");
        return 1;
    }
    if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_ADMIN)) {
        warnx("error: CAP_NET_ADMIN is required");
        return 1;
    }

    /*
     * Connect to netlink, load link cache from kernel.
     */
    struct nl_sock *sk;
    struct nl_cache *link_cache;
    int err;
 
    sk = nl_socket_alloc();
    assert(sk);
    err = nl_connect(sk, NETLINK_ROUTE);
    if (err < 0) {
        warnx("nl_connect() failed: %s", nl_geterror(err));
        return 1;
    }
    err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache);
    if (err < 0) {
        warnx("rtnl_link_alloc_cache() failed: %s", nl_geterror(err));
        return 1;
    }
   
    /*
     * Retrieve container network configuration -- IP address and
     * default gateway.
     */
    struct rtnl_link *l_veth;
    l_veth = rtnl_link_get_by_name(link_cache, VETH_LINK_NAME);
    if (l_veth == NULL) {
        warnx("error: Could not get link information for %s", VETH_LINK_NAME);
        return 1;
    }
    struct nl_addr *veth_addr;
    err = get_link_inet_addr(sk, l_veth, &veth_addr);
    if (err) {
        warnx("error: Unable to determine IP address of %s",
                VETH_LINK_NAME);
        return 1;
    }
    struct nl_addr *gw_addr;
    err = get_default_gw_inet_addr(sk, &gw_addr);
    if (err) {
        warnx("error: get_deGfault_gw_inet_addr() failed");
        return 1;
    }
    if (gw_addr == NULL) {
        warnx("error: No default gateway found. This is currently "
                "not supported");
        return 1;
    }

    /*
     * Create bridge and tap interface, enslave veth and tap interfaces to
     * bridge.
     */
    err = create_bridge_link(sk, BRIDGE_LINK_NAME);
    if (err < 0) {
        warnx("create_bridge_link(%s) failed: %s", BRIDGE_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    int tap_fd;

    if (hypervisor == UKVM)
        err = create_tap_link(TAP_LINK_NAME, &tap_fd);
    else
        err = create_tap_link(TAP_LINK_NAME, NULL);
    if (err != 0) {
        warnx("create_tap_link(%s) failed: %s", TAP_LINK_NAME, strerror(err));
        return 1;
    }

    /* Refill link cache with newly-created interfaces */
    nl_cache_refill(sk, link_cache);

    struct rtnl_link *l_bridge;
    l_bridge = rtnl_link_get_by_name(link_cache, BRIDGE_LINK_NAME);
    if (l_bridge == NULL) {
        warnx("error: Could not get link information for %s", BRIDGE_LINK_NAME);
        return 1;
    }
    struct rtnl_link *l_tap;
    l_tap = rtnl_link_get_by_name(link_cache, TAP_LINK_NAME);
    if (l_tap == NULL) {
        warnx("error: Could not get link information for %s", TAP_LINK_NAME);
        return 1;
    }
    err = rtnl_link_enslave(sk, l_bridge, l_veth);
    if (err < 0) {
        warnx("error: Unable to enslave %s to %s: %s", VETH_LINK_NAME,
                BRIDGE_LINK_NAME, nl_geterror(err));
        return 1;
    }
    err = rtnl_link_enslave(sk, l_bridge, l_tap);
    if (err < 0) {
        warnx("error: Unable to enslave %s to %s: %s", TAP_LINK_NAME,
                BRIDGE_LINK_NAME, nl_geterror(err));
        return 1;
    }

    /*
     * Flush all IPv4 addresses from the veth interface. This is now safe
     * as we are good to commit and have retrieved the existing configuration.
     */
    struct rtnl_addr *flush_addr;
    flush_addr = rtnl_addr_alloc();
    assert(flush_addr);
    rtnl_addr_set_ifindex(flush_addr, rtnl_link_get_ifindex(l_veth));
    rtnl_addr_set_family(flush_addr, AF_INET);
    rtnl_addr_set_local(flush_addr, veth_addr);
    err = rtnl_addr_delete(sk, flush_addr, 0);
    if (err < 0) {
        warnx("error: Could not flush addresses on %s: %s", VETH_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    rtnl_addr_put(flush_addr);

    /* 
     * Bring up the tap and bridge interfaces.
     */
    struct rtnl_link *l_up;
    l_up = rtnl_link_alloc();
    assert(l_up);
    /* You'd think set_operstate was the thing to do here. It's not. */
    rtnl_link_set_flags(l_up, IFF_UP);
    err = rtnl_link_change(sk, l_tap, l_up, 0);
    if (err < 0) {
        warnx("error: rtnl_link_change(%s, UP) failed: %s", TAP_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    err = rtnl_link_change(sk, l_bridge, l_up, 0);
    if (err < 0) {
        warnx("error: rtnl_link_change(%s, UP) failed: %s", BRIDGE_LINK_NAME,
                nl_geterror(err));
        return 1;
    }
    rtnl_link_put(l_up);

    /*
     * Collect network configuration data.
     */
    char ip[AF_INET_BUFSIZE];
    if (inet_ntop(AF_INET, nl_addr_get_binary_addr(veth_addr), ip,
            sizeof ip) == NULL) {
        perror("inet_ntop()");
        return 1;
    }
    char uarg_ip[AF_INET_BUFSIZE];
    unsigned int prefixlen = nl_addr_get_prefixlen(veth_addr);
    snprintf(uarg_ip, sizeof uarg_ip, "%s/%u", ip, prefixlen);

    char uarg_gw[AF_INET_BUFSIZE];
    if (inet_ntop(AF_INET, nl_addr_get_binary_addr(gw_addr), uarg_gw,
            sizeof uarg_gw) == NULL) {
        perror("inet_ntop()");
        return 1;
    }

    /*
     * Build unikernel and hypervisor arguments.
     */
    ptrvec* uargpv = pvnew();
    char *uarg_buf;
    /*
     * QEMU/KVM:
     * /usr/bin/qemu-system-x86_64 <qemu args> -kernel <unikernel> -append "<unikernel args>"
     */
    if (hypervisor == QEMU || hypervisor == KVM) {
        pvadd(uargpv, "/usr/bin/qemu-system-x86_64");
        pvadd(uargpv, "-nodefaults");
        pvadd(uargpv, "-no-acpi");
        pvadd(uargpv, "-display");
        pvadd(uargpv, "none");
        pvadd(uargpv, "-serial");
        pvadd(uargpv, "stdio");
        pvadd(uargpv, "-m");
        pvadd(uargpv, "512");
        if (hypervisor == KVM) {
            pvadd(uargpv, "-enable-kvm");
            pvadd(uargpv, "-cpu");
            pvadd(uargpv, "host");
        }
        else {
            /*
             * Required for AESNI use in Mirage.
             */
            pvadd(uargpv, "-cpu");
            pvadd(uargpv, "Westmere");
        }
        pvadd(uargpv, "-device");
        char *guest_mac = generate_mac();
        assert(guest_mac);
        err = asprintf(&uarg_buf, "virtio-net-pci,netdev=n0,mac=%s", guest_mac);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        pvadd(uargpv, "-netdev");
        err = asprintf(&uarg_buf, "tap,id=n0,ifname=%s,script=no,downscript=no",
            TAP_LINK_NAME);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        pvadd(uargpv, "-kernel");
        pvadd(uargpv, unikernel);
        pvadd(uargpv, "-append");
        /*
         * TODO: Replace any occurences of ',' with ',,' in -append, because
         * QEMU arguments are insane.
         */
        char cmdline[1024];
        char *cmdline_p = cmdline;
        size_t cmdline_free = sizeof cmdline;
        for (; *argv; argc--, argv++) {
            size_t alen = snprintf(cmdline_p, cmdline_free, "%s%s", *argv,
                    (argc > 1) ? " " : "");
            if (alen >= cmdline_free) {
                warnx("error: Command line too long");
                return 1;
            }
            cmdline_free -= alen;
            cmdline_p += alen;
        }
        size_t alen = snprintf(cmdline_p, cmdline_free,
                "--ipv4=%s --ipv4-gateway=%s", uarg_ip, uarg_gw);
        if (alen >= cmdline_free) {
            warnx("error: Command line too long");
            return 1;
        }
        pvadd(uargpv, cmdline);
    }
    /*
     * UKVM:
     * /unikernel/ukvm <ukvm args> <unikernel> -- <unikernel args>
     */
    else if (hypervisor == UKVM) {
        pvadd(uargpv, "/unikernel/ukvm");
        err = asprintf(&uarg_buf, "--net=@%d", tap_fd);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        pvadd(uargpv, "--");
        pvadd(uargpv, unikernel);
        for (; *argv; argc--, argv++) {
            pvadd(uargpv, *argv);
        }
        err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
    }
    /*
     * UNIX:
     * <unikernel> <unikernel args>
     */
    else if (hypervisor == UNIX) {
        pvadd(uargpv, unikernel);
        err = asprintf(&uarg_buf, "--interface=%s", TAP_LINK_NAME);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        for (; *argv; argc--, argv++) {
            pvadd(uargpv, *argv);
        }
        err = asprintf(&uarg_buf, "--ipv4=%s", uarg_ip);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
        err = asprintf(&uarg_buf, "--ipv4-gateway=%s", uarg_gw);
        assert(err != -1);
        pvadd(uargpv, uarg_buf);
    }
    char **uargv = (char **)pvfinal(uargpv);

    /*
     * Done with netlink, free all resources and close socket.
     */
    rtnl_link_put(l_veth);
    rtnl_link_put(l_bridge);
    rtnl_link_put(l_tap);
    nl_addr_put(veth_addr);
    nl_addr_put(gw_addr);

    nl_cache_free(link_cache);
    nl_close(sk);
    nl_socket_free(sk);

    /*
     * Drop all capabilities except CAP_NET_BIND_SERVICE.
     */
    capng_clear(CAPNG_SELECT_BOTH);
    capng_update(CAPNG_ADD,
            CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_INHERITABLE,
            CAP_NET_BIND_SERVICE);
    if (capng_apply(CAPNG_SELECT_BOTH) != 0) {
        warnx("error: Could not drop capabilities");
        return 1;
    }

    /*
     * Run the unikernel.
     */
    err = execv(uargv[0], uargv);
    warn("error: execv() of %s failed", uargv[0]);
    return 1;
}
Ejemplo n.º 6
0
int configure_loopback_interface() {
  struct nl_sock *sock = NULL;
  struct rtnl_addr *addr = NULL;
  struct nl_addr* lo_addr = NULL;
  struct nl_cache *cache = NULL;
  struct rtnl_link *link = NULL, *link2 = NULL;
  int err, nlflags = NLM_F_CREATE, ret = 0;
 
  if(!want_cap(CAP_NET_ADMIN)) {
    errWarn("Cannot set the CAP_NET_ADMIN effective capability");
    return -1;
  }
  
  sock = nl_socket_alloc();
  if(sock == NULL) {
    errWarn("nl_socket_alloc");
    return -1;
  }
  if((err = nl_connect(sock, NETLINK_ROUTE)) < 0) {
    fprintf(stderr, "Unable to connect to netlink: %s\n", nl_geterror(err));
    ret = -1;
    goto out2;
  }
  if(rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache) < 0) {
    ret = -1;
    goto out;
  }
  link = rtnl_link_get_by_name(cache, "lo");
  if (link == NULL) {
    ret = -1;
    goto out;
  }
  addr = rtnl_addr_alloc();
  if(addr == NULL) {
    ret = -1;
    goto out;
  }
 
  rtnl_addr_set_link(addr, link);
  rtnl_addr_set_family(addr, AF_INET);
  if((err = nl_addr_parse("127.0.0.1/8", AF_INET, &lo_addr)) < 0) {
    fprintf(stderr, "Unable to parse address: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }
  if((err = rtnl_addr_set_local(addr, lo_addr)) < 0) {
    fprintf(stderr, "Unable to set address: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }
  nl_addr_put(lo_addr);
  lo_addr = NULL;
  if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0) {
    fprintf(stderr, "Unable to add address: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }

  rtnl_addr_set_family(addr, AF_INET6);
  if((err = nl_addr_parse("::1/128", AF_INET6, &lo_addr)) < 0) {
    fprintf(stderr, "Unable to parse address: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }
  if((err = rtnl_addr_set_local(addr, lo_addr)) < 0) {
    fprintf(stderr, "Unable to set address: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }
  nl_addr_put(lo_addr);
  lo_addr = NULL;
  if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0) {
    fprintf(stderr, "Unable to add address: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }
  link2 = rtnl_link_alloc();
  if(link2 == NULL) {
    ret = -1;
    goto out;
  }
  rtnl_link_set_flags(link2, IFF_UP);
  if((err = rtnl_link_change(sock, link, link2, 0)) < 0) {
    fprintf(stderr, "Unable to change link: %s\n", nl_geterror(err));
    ret = -1;
    goto out;
  }

out:
  if(lo_addr!=NULL)
    nl_addr_put(lo_addr);
  if(link2!=NULL)  
    rtnl_link_put(link2);
  if(link!=NULL)  
    rtnl_link_put(link);
  if(cache!=NULL)
    nl_cache_put(cache);
  if(addr!=NULL)
    rtnl_addr_put(addr);
  nl_close(sock);
out2:
  nl_socket_free(sock);

  drop_caps();

  return ret;
}
Ejemplo n.º 7
0
int main(int argc, char *argv[])
{
	struct nl_sock *nl_sock;
	struct nl_cache *link_cache;
	int ifindex;
	int ret = 0;
	int err = 0;

	if (argc < 2)
	{
		printf("%s ip gw on/off tip\n", argv[0]);
		return -1;
	}

//link
	if (err = rtnl_route_read_table_names(ROUTE_TABLE)) {
		printf("failed to read %s. err = %s\n", ROUTE_TABLE, nl_geterror(err));
		return -1;;
	}

	nl_sock = nl_socket_alloc();
	if (NULL == nl_sock) {
		printf("failed to alloc netlink handler.\n");
		return -1;
	}

	if (err = nl_connect(nl_sock, NETLINK_ROUTE)) {
		printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}

	if (err = rtnl_link_alloc_cache(nl_sock, AF_INET, &link_cache))
	{
		printf("failed to allocate link cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}

	ifindex = rtnl_link_name2i(link_cache, NAME);
	if (0 == ifindex) {
		printf("%s - failed to find.\n", NAME);
		ret = -1;
		goto release_link_cache;
	}

	struct rtnl_link * link = rtnl_link_get(link_cache, ifindex);
	if (link == NULL)
	{
		printf("can't get link.\n");
		ret = -1;
		goto release_link_cache;
	}
	//rtnl_link_get_by_name

	struct nl_addr *lladdr = rtnl_link_get_addr(link);
	if (NULL == lladdr || AF_LLC != nl_addr_get_family(lladdr)) {
		printf("failed to get MAC\n");
		ret = -1;
		goto release_link;
	}

	uint8_t mac_address[ETHER_ADDR_LEN];
	memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN);
	printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
		 mac_address[0],
		 mac_address[1],
		 mac_address[2],
		 mac_address[3],
		 mac_address[4],
		 mac_address[5]);

//addr 
	struct nl_cache * addr_cache;
	if (err  = rtnl_addr_alloc_cache(nl_sock, &addr_cache))
	{
		printf("fail to get addr_cache\n");
		ret = -1;
		goto release_link;
	}
	struct rtnl_addr *addr = rtnl_addr_alloc();
	rtnl_addr_set_ifindex(addr, ifindex);
	rtnl_addr_set_family(addr, AF_INET);
	int prefixlen = 16;
	nl_cache_foreach_filter(addr_cache, (struct nl_object *)addr, get_ip, &prefixlen);
	nl_cache_free(addr_cache);

	uint32_t ipaddr = inet_addr(argv[1]);
	struct nl_addr * local = nl_addr_build(AF_INET, &ipaddr, sizeof(ipaddr));
	rtnl_addr_set_local(addr, local);
	rtnl_addr_set_ifindex(addr, ifindex);
	rtnl_addr_set_family(addr, AF_INET);
	rtnl_addr_set_prefixlen(addr, 32);

	if (!strcmp(argv[2], "on"))
	{
		if (err = rtnl_addr_add(nl_sock, addr, 0))
		{
			printf("fail to add addr %s\n", nl_geterror(err));
			ret = -1;
			goto release_addr;
		}
	}
	else
	{
		if (err = rtnl_addr_delete(nl_sock, addr, 0))
		{
			printf("fail to del addr %s\n", nl_geterror(err));
			ret = -1;
			goto release_addr;
		}
		
	}
//neigh
	struct nl_cache * neigh_cache;
	if (err = rtnl_neigh_alloc_cache(nl_sock, &neigh_cache))
	{
		printf("failed to allocate neighbor cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_neigh_cache;
	}

	uint32_t gw = inet_addr(argv[3]);
	struct nl_addr * gw_addr = nl_addr_build(AF_INET, &gw, sizeof(gw));

	struct rtnl_neigh * neigh = rtnl_neigh_get(neigh_cache, ifindex, gw_addr);
	if (neigh) {
		// It's optional
		struct nl_addr * lladdr = rtnl_neigh_get_lladdr(neigh);
		if (lladdr) {
			uint8_t mac_address[ETHER_ADDR_LEN];
			memcpy(mac_address, nl_addr_get_binary_addr(lladdr), ETHER_ADDR_LEN);
			printf("gw  %02X:%02X:%02X:%02X:%02X:%02X\n",
		 		mac_address[0],
		 		mac_address[1],
		 		mac_address[2],
		 		mac_address[3],
		 		mac_address[4],
		 		mac_address[5]);
		}
	}

	nl_addr_put(gw_addr);

//route
	struct nl_cache *route_cache;
	if (err = rtnl_route_alloc_cache(nl_sock, AF_INET, 0, &route_cache))
	{
		printf("failed to allocate route cache. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_neigh_cache;
	}

	struct rtnl_route *route = rtnl_route_alloc();
	struct nl_addr * taddr;
	err = nl_addr_parse(argv[4], AF_INET, &taddr);
        if (err)
        {
                printf("failed to get taddr. err = %s\n", nl_geterror(err));
                ret = -1;
                goto release_route_cache;
                
        }

	nl_cache_foreach_filter(route_cache, OBJ_CAST(route), get_route, NULL);
/*
	struct nl_sock *nl_fib_sock;
	nl_fib_sock = nl_socket_alloc();
	if (err = nl_connect(nl_fib_sock, NETLINK_FIB_LOOKUP)) {
		printf("failed to connect NETLINK_ROUTE. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_nl;
	}
	struct nl_dump_params params = {
		.dp_fd = stdout,
		.dp_type = NL_DUMP_DETAILS,
	};

	struct nl_cache *route_cache = flnl_result_alloc_cache();

        struct flnl_request *req = flnl_request_alloc();
        struct nl_addr * taddr;
	err = nl_addr_parse(argv[4], AF_INET, &taddr);
	if (err)
	{
		printf("failed to get taddr. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_route;
		
	}
	int table = RT_TABLE_UNSPEC, scope = RT_SCOPE_UNIVERSE;
        flnl_request_set_addr(req, taddr);
	flnl_request_set_table(req, table);
	flnl_request_set_scope(req, scope);
        err = flnl_lookup(nl_fib_sock, req, route_cache);
	if (err)
	{
		printf("failed to fib lookup. err = %s\n", nl_geterror(err));
		ret = -1;
		goto release_route_addr;
	}
	
	nl_cache_dump(route_cache, &params);

release_route_addr:
	nl_addr_put(taddr);	

release_route:
        nl_cache_free(route_cache);
	nl_object_put(OBJ_CAST(req));

	nl_close(nl_fib_sock);
	nl_socket_free(nl_fib_sock);
*/
release_route_cache:
	nl_cache_free(route_cache);
release_neigh_cache:
	nl_cache_free(neigh_cache);
release_addr:
	nl_addr_put(local);
	rtnl_addr_put(addr);
release_link:
	rtnl_link_put(link);
release_link_cache:
	nl_cache_free(link_cache);
release_nl:
	nl_close(nl_sock);
	nl_socket_free(nl_sock);

	return ret;
}
Ejemplo n.º 8
0
int main(int argc, char *argv[])
{
	struct nl_sock *sock;
	struct rtnl_addr *addr;
	struct nl_cache *link_cache, *addr_cache;
	struct nl_dump_params params = {
		.dp_type = NL_DUMP_LINE,
		.dp_nl_cb = print_prefix,
		.dp_fd = stdout,
	};
	int dump_env = 0;

	sock = nl_cli_alloc_socket();
	nl_cli_connect(sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(sock);
	addr_cache = nl_cli_addr_alloc_cache(sock);
	addr = nl_cli_addr_alloc();

	for (;;) {
		int c, optidx = 0;
		enum {
			ARG_FAMILY = 257,
			ARG_LABEL = 258,
			ARG_PEER,
			ARG_SCOPE,
			ARG_BROADCAST,
			ARG_DETAILS,
			ARG_ENV,
			ARG_PREFIX,
			ARG_PREFERRED,
			ARG_VALID,
		};
		static struct option long_opts[] = {
			{ "details", 0, 0, ARG_DETAILS },
			{ "env", 0, 0, ARG_ENV },
			{ "prefix", 1, 0, ARG_PREFIX },
			{ "help", 0, 0, 'h' },
			{ "version", 0, 0, 'v' },
			{ "local", 1, 0, 'a' },
			{ "dev", 1, 0, 'd' },
			{ "family", 1, 0, ARG_FAMILY },
			{ "label", 1, 0, ARG_LABEL },
			{ "peer", 1, 0, ARG_PEER },
			{ "scope", 1, 0, ARG_SCOPE },
			{ "broadcast", 1, 0, ARG_BROADCAST },
			{ "preferred", 1, 0, ARG_PREFERRED },
			{ "valid", 1, 0, ARG_VALID },
			{ 0, 0, 0, 0 }
		};

		c = getopt_long(argc, argv, "46hva:d:", long_opts, &optidx);
		if (c == -1)
			break;

		switch (c) {
		case '?': exit(NLE_INVAL);
		case '4': rtnl_addr_set_family(addr, AF_INET); break;
		case '6': rtnl_addr_set_family(addr, AF_INET6); break;
		case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break;
		case ARG_ENV: dump_env = 1; break;
		case ARG_PREFIX: prefix = strdup(optarg); break;
		case 'h': print_usage(); break;
		case 'v': nl_cli_print_version(); break;
		case 'a': nl_cli_addr_parse_local(addr, optarg); break;
		case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break;
		case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break;
		case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break;
		case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break;
		case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break;
		case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break;
		case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break;
		case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break;
		}
	}

	if (dump_env)
		nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), env_dump,
					&params);
	else
		nl_cache_dump_filter(addr_cache, &params, OBJ_CAST(addr));

	return 0;
}