Example #1
0
static int get_mcast_mac_ipv6(struct nl_addr *dst, struct nl_addr **ll_addr)
{
	uint8_t mac_addr[6] = {0x33, 0x33};

	memcpy(mac_addr + 2, (uint8_t *)nl_addr_get_binary_addr(dst) + 12, 4);

	*ll_addr = nl_addr_build(AF_LLC, mac_addr, sizeof(mac_addr));

	return *ll_addr == NULL ? -EINVAL : 0;
}
Example #2
0
static int get_link_local_mac_ipv6(struct nl_addr *dst,
				   struct nl_addr **ll_addr)
{
	uint8_t mac_addr[6];

	memcpy(mac_addr + 3, (uint8_t *)nl_addr_get_binary_addr(dst) + 13, 3);
	memcpy(mac_addr, (uint8_t *)nl_addr_get_binary_addr(dst) + 8, 3);
	mac_addr[0] ^= 2;

	*ll_addr = nl_addr_build(AF_LLC, mac_addr, sizeof(mac_addr));
	return *ll_addr == NULL ? -EINVAL : 0;
}
Example #3
0
static int result_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
			     struct nlmsghdr *n, struct nl_parser_param *pp)
{
	struct flnl_result *res;
	struct fib_result_nl *fr;
	struct nl_addr *addr;
	int err = -EINVAL;

	res = flnl_result_alloc();
	if (!res)
		goto errout;

	res->ce_msgtype = n->nlmsg_type;

	res->fr_req = flnl_request_alloc();
	if (!res->fr_req)
		goto errout;

	fr = nlmsg_data(n);
	addr = nl_addr_build(AF_INET, &fr->fl_addr, 4);
	if (!addr)
		goto errout;
	err = flnl_request_set_addr(res->fr_req, addr);
	nl_addr_put(addr);
	if (err < 0)
		goto errout;

	flnl_request_set_fwmark(res->fr_req, fr->fl_fwmark);
	flnl_request_set_tos(res->fr_req, fr->fl_tos);
	flnl_request_set_scope(res->fr_req, fr->fl_scope);
	flnl_request_set_table(res->fr_req, fr->tb_id_in);

	res->fr_table_id = fr->tb_id;
	res->fr_prefixlen = fr->prefixlen;
	res->fr_nh_sel = fr->nh_sel;
	res->fr_type = fr->type;
	res->fr_scope = fr->scope;
	res->fr_error = fr->err;

	err = pp->pp_cb((struct nl_object *) res, pp);
	if (err < 0)
		goto errout;

	/* REAL HACK, fib_lookup doesn't support ACK nor does it
	 * send a DONE message, enforce end of message stream
	 * after just the first message */
	err = NL_STOP;

errout:
	flnl_result_put(res);
	return err;
}
Example #4
0
static int get_mcast_mac_ipv4(struct nl_addr *dst, struct nl_addr **ll_addr)
{
	uint8_t mac_addr[6] = {0x01, 0x00, 0x5E};
	uint32_t addr = be32toh(*(__be32 *)nl_addr_get_binary_addr(dst));

	mac_addr[5] = addr & 0xFF;
	addr >>= 8;
	mac_addr[4] = addr & 0xFF;
	addr >>= 8;
	mac_addr[3] = addr & 0x7F;

	*ll_addr = nl_addr_build(AF_LLC, mac_addr, sizeof(mac_addr));

	return *ll_addr == NULL ? -EINVAL : 0;
}
void
switchlink_linux_mac_update(switchlink_mac_addr_t mac_addr,
                            switchlink_handle_t bridge_h,
                            switchlink_handle_t intf_h, bool create) {
    switchlink_db_status_t status;
    uint32_t ifindex;

    if (!create) {
        status = switchlink_db_mac_get_intf(mac_addr, bridge_h, &intf_h);
        if (status != SWITCHLINK_DB_STATUS_SUCCESS) {
            assert(false);
            return;
        }
    }

    status = switchlink_db_interface_get_ifindex(intf_h, &ifindex);
    if (status != SWITCHLINK_DB_STATUS_SUCCESS) {
        assert(false);
        return;
    }

    struct nl_sock *nlsk = switchlink_get_nl_sock();
    if (!nlsk) {
        return;
    }

    struct nl_addr *nl_addr = nl_addr_build(AF_LLC, mac_addr, ETH_ALEN);
    struct rtnl_neigh *rtnl_neigh = rtnl_neigh_alloc();
    rtnl_neigh_set_ifindex(rtnl_neigh, ifindex);
    rtnl_neigh_set_lladdr(rtnl_neigh, nl_addr);
    rtnl_neigh_set_state(rtnl_neigh, rtnl_neigh_str2state("permanent"));
    rtnl_neigh_set_family(rtnl_neigh, AF_BRIDGE);

    if (create) {
        status = switchlink_db_mac_add(mac_addr, bridge_h, intf_h);
        assert(status == SWITCHLINK_DB_STATUS_SUCCESS);
        rtnl_neigh_add(nlsk, rtnl_neigh, NLM_F_CREATE|NLM_F_REPLACE);
    } else {
        status = switchlink_db_mac_delete(mac_addr, bridge_h);
        assert(status == SWITCHLINK_DB_STATUS_SUCCESS);
        rtnl_neigh_delete(nlsk, rtnl_neigh, 0);
    }
    rtnl_neigh_put(rtnl_neigh);
    nl_addr_put(nl_addr);
}
Example #6
0
File: inet6.c Project: Domikk/libnl
/**
 * Get IPv6 tokenized interface identifier
 * @arg link		Link object
 * @arg token		Tokenized interface identifier on success
 *
 * Returns the link's IPv6 tokenized interface identifier.
 *
 * @return 0 on success
 * @return -NLE_NOMEM  failure to allocate struct nl_addr result
 * @return -NLE_NOATTR configuration setting not available
 * @return -NLE_NOADDR tokenized interface identifier is not set
 */
int rtnl_link_inet6_get_token(struct rtnl_link *link, struct nl_addr **addr)
{
	struct inet6_data *id;

	if (!(id = rtnl_link_af_data(link, &inet6_ops)))
		return -NLE_NOATTR;

	*addr = nl_addr_build(AF_INET6, &id->i6_token, sizeof(id->i6_token));
	if (!*addr)
		return -NLE_NOMEM;
	if (nl_addr_iszero(*addr)) {
		nl_addr_put(*addr);
		*addr = NULL;
		return -NLE_NOADDR;
	}

	return 0;
}
Example #7
0
int main(int argc, char *argv[])
{
	struct rtnl_link *link;
	struct nl_cache *link_cache;
	struct nl_sock *sk;
        struct nl_addr* addr;
	int err, master_index;

	sk = nl_socket_alloc();
	if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) {
		nl_perror(err, "Unable to connect socket");
		return err;
	}

	if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) {
		nl_perror(err, "Unable to allocate cache");
		return err;
	}

	if (!(master_index = rtnl_link_name2i(link_cache, "eth0"))) {
		fprintf(stderr, "Unable to lookup eth0");
		return -1;
	}

	link = rtnl_link_macvtap_alloc();

	rtnl_link_set_link(link, master_index);

	addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN);
	rtnl_link_set_addr(link, addr);
	nl_addr_put(addr);

	rtnl_link_macvtap_set_mode(link, rtnl_link_macvtap_str2mode("bridge"));

	if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) {
		nl_perror(err, "Unable to add link");
		return err;
	}

	rtnl_link_put(link);
	nl_close(sk);

	return 0;
}
Example #8
0
int nl_bridge::fdb_timeout(rtnl_link *br_link, uint16_t vid,
                           const rofl::caddress_ll &mac) {
  int rv = 0;

  std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n(rtnl_neigh_alloc(),
                                                           rtnl_neigh_put);

  std::unique_ptr<nl_addr, decltype(&nl_addr_put)> h_src(
      nl_addr_build(AF_LLC, mac.somem(), mac.memlen()), nl_addr_put);

  rtnl_neigh_set_ifindex(n.get(), rtnl_link_get_ifindex(br_link));
  rtnl_neigh_set_master(n.get(), rtnl_link_get_master(br_link));
  rtnl_neigh_set_family(n.get(), AF_BRIDGE);
  rtnl_neigh_set_vlan(n.get(), vid);
  rtnl_neigh_set_lladdr(n.get(), h_src.get());
  rtnl_neigh_set_flags(n.get(), NTF_MASTER | NTF_EXT_LEARNED);
  rtnl_neigh_set_state(n.get(), NUD_REACHABLE);

  // find entry in local l2_cache
  std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n_lookup(
      NEIGH_CAST(nl_cache_search(l2_cache.get(), OBJ_CAST(n.get()))),
      rtnl_neigh_put);

  if (n_lookup) {
    // * remove l2 entry from kernel
    nl_msg *msg = nullptr;
    rtnl_neigh_build_delete_request(n.get(), NLM_F_REQUEST, &msg);
    assert(msg);

    // send the message and create new fdb entry
    if (nl->send_nl_msg(msg) < 0) {
      LOG(ERROR) << __FUNCTION__ << ": failed to send netlink message";
      return -EINVAL;
    }

    // XXX TODO maybe delete after NL event and not yet here
    nl_cache_remove(OBJ_CAST(n_lookup.get()));
  }

  return rv;
}
Example #9
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;
}
Example #10
0
File: ae.c Project: Domikk/libnl
int xfrmnl_ae_parse(struct nlmsghdr *n, struct xfrmnl_ae **result)
{
	struct xfrmnl_ae*    ae;
	struct nlattr           *tb[XFRMA_MAX + 1];
	struct xfrm_aevent_id*  ae_id;
	int err;

	ae = xfrmnl_ae_alloc();
	if (!ae) {
		err = -NLE_NOMEM;
		goto errout;
	}

	ae->ce_msgtype = n->nlmsg_type;
	ae_id = nlmsg_data(n);

	err = nlmsg_parse(n, sizeof(struct xfrm_aevent_id), tb, XFRMA_MAX, xfrm_ae_policy);
	if (err < 0)
		goto errout;

	ae->sa_id.daddr = nl_addr_build(ae_id->sa_id.family, &ae_id->sa_id.daddr, sizeof (ae_id->sa_id.daddr));
	ae->sa_id.family= ae_id->sa_id.family;
	ae->sa_id.spi   = ntohl(ae_id->sa_id.spi);
	ae->sa_id.proto = ae_id->sa_id.proto;
	ae->saddr       = nl_addr_build(ae_id->sa_id.family, &ae_id->saddr, sizeof (ae_id->saddr));
	ae->reqid       = ae_id->reqid;
	ae->flags       = ae_id->flags;
	ae->ce_mask |= (XFRM_AE_ATTR_DADDR | XFRM_AE_ATTR_FAMILY | XFRM_AE_ATTR_SPI |
					XFRM_AE_ATTR_PROTO | XFRM_AE_ATTR_SADDR | XFRM_AE_ATTR_REQID |
					XFRM_AE_ATTR_FLAGS);

	if (tb[XFRMA_MARK]) {
		struct xfrm_mark* m =   nla_data(tb[XFRMA_MARK]);
		ae->mark.m  =   m->m;
		ae->mark.v  =   m->v;
		ae->ce_mask |= XFRM_AE_ATTR_MARK;
	}

	if (tb[XFRMA_LTIME_VAL]) {
		struct xfrm_lifetime_cur* cur =   nla_data(tb[XFRMA_LTIME_VAL]);
		ae->lifetime_cur.bytes      =   cur->bytes;
		ae->lifetime_cur.packets    =   cur->packets;
		ae->lifetime_cur.add_time   =   cur->add_time;
		ae->lifetime_cur.use_time   =   cur->use_time;
		ae->ce_mask |= XFRM_AE_ATTR_LIFETIME;
	}

	if (tb[XFRM_AE_ETHR]) {
		ae->replay_maxage       =   *(uint32_t*)nla_data(tb[XFRM_AE_ETHR]);
		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXAGE;
	}

	if (tb[XFRM_AE_RTHR]) {
		ae->replay_maxdiff      =   *(uint32_t*)nla_data(tb[XFRM_AE_RTHR]);
		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_MAXDIFF;
	}

	if (tb[XFRMA_REPLAY_ESN_VAL]) {
		struct xfrm_replay_state_esn* esn =  nla_data (tb[XFRMA_REPLAY_ESN_VAL]);
		uint32_t len = sizeof (struct xfrmnl_replay_state_esn) +  (sizeof (uint32_t) * esn->bmp_len);

		if ((ae->replay_state_esn = calloc (1, len)) == NULL) {
			err = -ENOMEM;
			goto errout;
		}
		ae->replay_state_esn->oseq       =  esn->oseq;
		ae->replay_state_esn->seq        =  esn->seq;
		ae->replay_state_esn->oseq_hi    =  esn->oseq_hi;
		ae->replay_state_esn->seq_hi     =  esn->seq_hi;
		ae->replay_state_esn->replay_window   =   esn->replay_window;
		ae->replay_state_esn->bmp_len    =   esn->bmp_len;
		memcpy (ae->replay_state_esn->bmp, esn->bmp, sizeof (uint32_t) * esn->bmp_len);
		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE;
	}
	else
	{
		struct xfrm_replay_state* replay_state = nla_data (tb[XFRMA_REPLAY_VAL]);
		ae->replay_state.oseq       =   replay_state->oseq;
		ae->replay_state.seq        =   replay_state->seq;
		ae->replay_state.bitmap     =   replay_state->bitmap;
		ae->ce_mask |= XFRM_AE_ATTR_REPLAY_STATE;

		ae->replay_state_esn = NULL;
	}

	*result = ae;
	return 0;

errout:
	xfrmnl_ae_put(ae);
	return err;
}
/**
 * _route_add:
 * @route: the route to add
 * @family: address family, either %AF_INET or %AF_INET6
 * @dest: the route destination address, either a struct in_addr or a struct
 *   in6_addr depending on @family
 * @dest_prefix: the CIDR prefix of @dest
 * @gateway: the gateway through which to reach @dest, if any; given as a
 *   struct in_addr or struct in6_addr depending on @family
 * @flags: flags to pass to rtnl_route_add(), eg %NLM_F_REPLACE
 *
 * Returns: zero if succeeded or the netlink error otherwise.
 **/
static int
_route_add (struct rtnl_route *route,
            int family,
            const void *dest, /* in_addr or in6_addr */
            int dest_prefix,
            const void *gateway, /* in_addr or in6_addr */
            int flags)
{
	struct nl_sock *sk;
	struct nl_addr *dest_addr, *gw_addr;
	void *tmp_addr;
	int addrlen, err, log;

	if (family == AF_INET) {
		addrlen = sizeof (struct in_addr);
		log = LOGD_IP4;
	} else if (family == AF_INET6) {
		addrlen = sizeof (struct in6_addr);
		log = LOGD_IP6;
	} else
		g_assert_not_reached ();

	sk = nm_netlink_get_default_handle ();

	/* Build up the destination address */
	if (dest) {
		/* Copy to preserve const */
		tmp_addr = g_malloc0 (addrlen);
		memcpy (tmp_addr, dest, addrlen);

		dest_addr = nl_addr_build (family, tmp_addr, addrlen);
		g_free (tmp_addr);

		g_return_val_if_fail (dest_addr != NULL, -NLE_INVAL);
		nl_addr_set_prefixlen (dest_addr, dest_prefix);

		rtnl_route_set_dst (route, dest_addr);
		nl_addr_put (dest_addr);
	}

	/* Build up the gateway address */
	if (gateway) {
		tmp_addr = g_malloc0 (addrlen);
		memcpy (tmp_addr, gateway, addrlen);

		gw_addr = nl_addr_build (family, tmp_addr, addrlen);
		g_free (tmp_addr);

		if (gw_addr) {
			nl_addr_set_prefixlen (gw_addr, 0);
			rtnl_route_set_gateway (route, gw_addr);
			rtnl_route_set_scope (route, RT_SCOPE_UNIVERSE);
			nl_addr_put (gw_addr);
		} else
			nm_log_err (LOGD_DEVICE | log, "Invalid gateway");
	}

	err = rtnl_route_add (sk, route, flags);

	/* LIBNL Bug: Aliased ESRCH */
	if (err == -NLE_FAILURE)
		err = -NLE_OBJ_NOTFOUND;

	return err;
}
Example #12
0
int ip_addr(char *ip4addr, char *interface, cmd_t cmd)
{
    struct nl_handle *nlh = NULL;
    struct rtnl_addr *addr = NULL;
    struct nl_addr *nl_addr = NULL;
    uint32_t binaddr = 0;
    int iface_idx = -1;
    int err,ret = 0;

    if (init_handle(&nlh) != 0) {
        return -1;
    }

    iface_idx = if_nametoindex(interface);
    if (iface_idx < 0) {
        return -1;
    }

    addr = rtnl_addr_alloc ();
    if (!addr) {
        return -1;
    }

    if (inet_pton(AF_INET, ip4addr, &binaddr) == 0) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
                          "not valid ip address\n");
        ret = -1;
        goto out;
    }

    nl_addr = nl_addr_build (AF_INET, &binaddr, sizeof(binaddr));
    if (!nl_addr) {
        ret = -1;
        goto out;
    }

    rtnl_addr_set_local (addr, nl_addr);
    nl_addr_put (nl_addr);

    rtnl_addr_set_ifindex (addr, iface_idx);
    switch (cmd) {
    case ADD_IP:
        err = rtnl_addr_add (nlh, addr, 0);
        if ( err == -17 ) {
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
                              "%s is already on %s interface\n", ip4addr, interface);
            ret = 0;
        } else if ( err < 0 ) {
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
                              "error %d returned from rtnl_addr_add():\n%s\n",
                              err, nl_geterror());
            ret = -1;
        } else {
            ret = 0;
        }
        break;
    case DEL_IP:
        err = rtnl_addr_delete (nlh, addr, 0);
        if (err == -99) {
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
                              "%s is not present on %s interface\n", ip4addr, interface);
            ret = 0;
        } else if (err < 0) {
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
                              "error %d returned from rtnl_addr_delete():\n%s\n",
                              err, nl_geterror());
            ret = -1;
        } else {
            ret = 0;
        }
        break;
    }

out:
    if (addr) {
        rtnl_addr_put (addr);
    }
    if (nlh) {
        nl_close(nlh);
        nl_handle_destroy(nlh);
    }
    return ret;
}
Example #13
0
TError TNlLink::AddXVlan(const std::string &vlantype,
                         const std::string &master,
                         uint32_t type,
                         const std::string &hw,
                         int mtu) {
    TError error = TError::Success();
    int ret;
    uint32_t masterIdx;
    struct nl_msg *msg;
    struct nlattr *linkinfo, *infodata;
    struct ifinfomsg ifi = { 0 };
    struct ether_addr *ea = nullptr;
    auto Name = GetName();

    if (hw.length()) {
        // FIXME THREADS
        ea = ether_aton(hw.c_str());
        if (!ea)
            return TError(EError::Unknown, "Invalid " + vlantype + " mac address " + hw);
    }

    TNlLink masterLink(Nl, master);
    error = masterLink.Load();
    if (error)
        return error;
    masterIdx = masterLink.GetIndex();

    msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_CREATE);
    if (!msg)
        return TError(EError::Unknown, "Unable to add " + vlantype + ": no memory");

    ret = nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO);
    if (ret < 0) {
        error = TError(EError::Unknown, "Unable to add " + vlantype + ": " + nl_geterror(ret));
        goto free_msg;
    }

    /* link configuration */
    ret = nla_put(msg, IFLA_LINK, sizeof(uint32_t), &masterIdx);
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to put IFLA_LINK: ") + nl_geterror(ret));
        goto free_msg;
    }
    ret = nla_put(msg, IFLA_IFNAME, Name.length() + 1, Name.c_str());
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to put IFLA_IFNAME: ") + nl_geterror(ret));
        goto free_msg;
    }

    if (mtu > 0) {
        ret = nla_put(msg, IFLA_MTU, sizeof(int), &mtu);
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_MTU: ") + nl_geterror(ret));
            goto free_msg;
        }
    }

    if (ea) {
        struct nl_addr *addr = nl_addr_build(AF_LLC, ea, ETH_ALEN);
        ret = nla_put(msg, IFLA_ADDRESS, nl_addr_get_len(addr), nl_addr_get_binary_addr(addr));
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_ADDRESS: ") + nl_geterror(ret));
            goto free_msg;
        }
        nl_addr_put(addr);
    }

    /* link type */
    linkinfo = nla_nest_start(msg, IFLA_LINKINFO);
    if (!linkinfo) {
        error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_LINKINFO");
        goto free_msg;
    }
    ret = nla_put(msg, IFLA_INFO_KIND, vlantype.length() + 1, vlantype.c_str());
    if (ret < 0) {
        error = TError(EError::Unknown, std::string("Unable to put IFLA_INFO_KIND: ") + nl_geterror(ret));
        goto free_msg;
    }

    /* xvlan specific */
    infodata = nla_nest_start(msg, IFLA_INFO_DATA);
    if (!infodata) {
        error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_INFO_DATA");
        goto free_msg;
    }

    if (vlantype == "macvlan") {
        ret = nla_put(msg, IFLA_MACVLAN_MODE, sizeof(uint32_t), &type);
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_MACVLAN_MODE: ") + nl_geterror(ret));
            goto free_msg;
        }
#ifdef IFLA_IPVLAN_MAX
    } else if (vlantype == "ipvlan") {
        uint16_t mode = type;
        ret = nla_put(msg, IFLA_IPVLAN_MODE, sizeof(uint16_t), &mode);
        if (ret < 0) {
            error = TError(EError::Unknown, std::string("Unable to put IFLA_IPVLAN_MODE: ") + nl_geterror(ret));
            goto free_msg;
        }
#endif
    }
    nla_nest_end(msg, infodata);
    nla_nest_end(msg, linkinfo);

    L() << "netlink: add " << vlantype << " " << Name << " master " << master
        << " type " << type << " hw " << hw << " mtu " << mtu << std::endl;

    ret = nl_send_sync(GetSock(), msg);
    if (ret)
        return Error(ret, "Cannot add " + vlantype);

    return Load();

free_msg:
    nlmsg_free(msg);
    return error;

}
Example #14
0
int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
{
	struct idiagnl_msg *msg = NULL;
	struct inet_diag_msg *raw_msg = NULL;
	struct nl_addr *src = NULL, *dst = NULL;
	struct nlattr *tb[IDIAG_ATTR_MAX];
	int err = 0;

	msg = idiagnl_msg_alloc();
	if (!msg)
		goto errout_nomem;

	err = nlmsg_parse(nlh, sizeof(struct inet_diag_msg), tb, IDIAG_ATTR_MAX,
			ext_policy);
	if (err < 0)
		goto errout;

	raw_msg = nlmsg_data(nlh);
	msg->idiag_family = raw_msg->idiag_family;
	msg->idiag_state = raw_msg->idiag_state;
	msg->idiag_timer = raw_msg->idiag_timer;
	msg->idiag_retrans = raw_msg->idiag_retrans;
	msg->idiag_expires = raw_msg->idiag_expires;
	msg->idiag_rqueue = raw_msg->idiag_rqueue;
	msg->idiag_wqueue = raw_msg->idiag_wqueue;
	msg->idiag_uid = raw_msg->idiag_uid;
	msg->idiag_inode = raw_msg->idiag_inode;
	msg->idiag_sport = raw_msg->id.idiag_sport;
	msg->idiag_dport = raw_msg->id.idiag_dport;
	msg->idiag_ifindex = raw_msg->id.idiag_if;

	dst = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
			sizeof(raw_msg->id.idiag_dst));
	if (!dst)
		goto errout_nomem;

	err = idiagnl_msg_set_dst(msg, dst);
	if (err < 0)
		goto errout;

	nl_addr_put(dst);

	src = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
			sizeof(raw_msg->id.idiag_src));
	if (!src)
		goto errout_nomem;

	err = idiagnl_msg_set_src(msg, src);
	if (err < 0)
		goto errout;

	nl_addr_put(src);

	if (tb[IDIAG_ATTR_TOS])
		msg->idiag_tos = nla_get_u8(tb[IDIAG_ATTR_TOS]);

	if (tb[IDIAG_ATTR_TCLASS])
		msg->idiag_tclass = nla_get_u8(tb[IDIAG_ATTR_TCLASS]);

	if (tb[IDIAG_ATTR_SHUTDOWN])
		msg->idiag_shutdown = nla_get_u8(tb[IDIAG_ATTR_SHUTDOWN]);

	if (tb[IDIAG_ATTR_CONG])
		msg->idiag_cong = nla_strdup(tb[IDIAG_ATTR_CONG]);

	if (tb[IDIAG_ATTR_INFO])
		nla_memcpy(&msg->idiag_tcpinfo, tb[IDIAG_ATTR_INFO],
				sizeof(msg->idiag_tcpinfo));

	if (tb[IDIAG_ATTR_MEMINFO]) {
		struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
		struct inet_diag_meminfo *raw_minfo = NULL;

		if (!minfo)
			goto errout_nomem;

		raw_minfo = (struct inet_diag_meminfo *)
			nla_data(tb[IDIAG_ATTR_MEMINFO]);

		idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
		idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
		idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem);
		idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);

		msg->idiag_meminfo = minfo;
	}

	if (tb[IDIAG_ATTR_VEGASINFO]) {
		struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
		struct tcpvegas_info *raw_vinfo = NULL;

		if (!vinfo)
			goto errout_nomem;

		raw_vinfo = (struct tcpvegas_info *)
			nla_data(tb[IDIAG_ATTR_VEGASINFO]);

		idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
		idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
		idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt);
		idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);

		msg->idiag_vegasinfo = vinfo;
	}

	if (tb[IDIAG_ATTR_SKMEMINFO])
		nla_memcpy(&msg->idiag_skmeminfo, tb[IDIAG_ATTR_SKMEMINFO],
				sizeof(msg->idiag_skmeminfo));

	*result = msg;
	return 0;

errout:
	idiagnl_msg_put(msg);
	return err;

errout_nomem:
	err = -NLE_NOMEM;
	goto errout;
}
Example #15
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;
}
Example #16
0
int nl_bridge::learn_source_mac(rtnl_link *br_link, packet *p) {
  // we still assume vlan filtering bridge
  assert(rtnl_link_get_family(br_link) == AF_BRIDGE);

  VLOG(2) << __FUNCTION__ << ": pkt " << p << " on link " << OBJ_CAST(br_link);

  rtnl_link_bridge_vlan *br_vlan = rtnl_link_bridge_get_port_vlan(br_link);

  if (br_vlan == nullptr) {
    LOG(ERROR) << __FUNCTION__
               << ": only the vlan filtering bridge is supported";
    return -EINVAL;
  }

  // parse ether frame and check for vid
  vlan_hdr *hdr = reinterpret_cast<basebox::vlan_hdr *>(p->data);
  uint16_t vid = 0;

  // XXX TODO maybe move this to the utils to have a std lib for parsing the
  // ether frame
  switch (ntohs(hdr->eth.h_proto)) {
  case ETH_P_8021Q:
    // vid
    vid = ntohs(hdr->vlan);
    break;
  default:
    // no vid, set vid to pvid
    vid = br_vlan->pvid;
    LOG(WARNING) << __FUNCTION__ << ": assuming untagged for ethertype "
                 << std::showbase << std::hex << ntohs(hdr->eth.h_proto);
    break;
  }

  // verify that the vid is in use here
  if (!is_vid_set(vid, br_vlan->vlan_bitmap)) {
    LOG(WARNING) << __FUNCTION__ << ": got packet on unconfigured port";
    return -ENOTSUP;
  }

  // set nl neighbour to NL
  std::unique_ptr<nl_addr, decltype(&nl_addr_put)> h_src(
      nl_addr_build(AF_LLC, hdr->eth.h_source, sizeof(hdr->eth.h_source)),
      nl_addr_put);

  if (!h_src) {
    LOG(ERROR) << __FUNCTION__ << ": failed to allocate src mac";
    return -ENOMEM;
  }

  std::unique_ptr<rtnl_neigh, decltype(&rtnl_neigh_put)> n(rtnl_neigh_alloc(),
                                                           rtnl_neigh_put);

  rtnl_neigh_set_ifindex(n.get(), rtnl_link_get_ifindex(br_link));
  rtnl_neigh_set_master(n.get(), rtnl_link_get_master(br_link));
  rtnl_neigh_set_family(n.get(), AF_BRIDGE);
  rtnl_neigh_set_vlan(n.get(), vid);
  rtnl_neigh_set_lladdr(n.get(), h_src.get());
  rtnl_neigh_set_flags(n.get(), NTF_MASTER | NTF_EXT_LEARNED);
  rtnl_neigh_set_state(n.get(), NUD_REACHABLE);

  // check if entry already exists in cache
  if (is_mac_in_l2_cache(n.get())) {
    return 0;
  }

  nl_msg *msg = nullptr;
  rtnl_neigh_build_add_request(n.get(),
                               NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, &msg);
  assert(msg);

  // send the message and create new fdb entry
  if (nl->send_nl_msg(msg) < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed to send netlink message";
    return -EINVAL;
  }

  // cache the entry
  if (nl_cache_add(l2_cache.get(), OBJ_CAST(n.get())) < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed to add entry to l2_cache "
               << OBJ_CAST(n.get());
    return -EINVAL;
  }

  VLOG(2) << __FUNCTION__ << ": learned new source mac " << OBJ_CAST(n.get());

  return 0;
}
Example #17
0
File: inet6.c Project: Domikk/libnl
static void inet6_dump_details(struct rtnl_link *link,
				struct nl_dump_params *p, void *data)
{
	struct inet6_data *i6 = data;
	struct nl_addr *addr;
	char buf[64], buf2[64];
	int i, n = 0;

	nl_dump_line(p, "    ipv6 max-reasm-len %s",
		nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf)));

	nl_dump(p, " <%s>\n",
		inet6_flags2str(i6->i6_flags, buf, sizeof(buf)));


	nl_dump_line(p, "      create-stamp %.2fs reachable-time %s",
		(double) i6->i6_cacheinfo.tstamp / 100.,
		nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf)));

	nl_dump(p, " retrans-time %s\n",
		nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf)));

	addr = nl_addr_build(AF_INET6, &i6->i6_token, sizeof(i6->i6_token));
	nl_dump(p, "      token %s\n",
		nl_addr2str(addr, buf, sizeof(buf)));
	nl_addr_put(addr);

	nl_dump(p, "      link-local address mode %s\n",
		rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode,
						buf, sizeof(buf)));

	nl_dump_line(p, "      devconf:\n");
	nl_dump_line(p, "      ");

	for (i = 0; i < DEVCONF_MAX; i++) {
		uint32_t value = i6->i6_conf[i];
		int x, offset;

		switch (i) {
		case DEVCONF_TEMP_VALID_LFT:
		case DEVCONF_TEMP_PREFERED_LFT:
			nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2));
			break;

		case DEVCONF_RTR_PROBE_INTERVAL:
		case DEVCONF_RTR_SOLICIT_INTERVAL:
		case DEVCONF_RTR_SOLICIT_DELAY:
			nl_msec2str(value, buf2, sizeof(buf2));
			break;

		default:
			snprintf(buf2, sizeof(buf2), "%u", value);
			break;
			
		}

		inet6_devconf2str(i, buf, sizeof(buf));

		offset = 23 - strlen(buf2);
		if (offset < 0)
			offset = 0;

		for (x = strlen(buf); x < offset; x++)
			buf[x] = ' ';

		strncpy(&buf[offset], buf2, strlen(buf2));

		nl_dump_line(p, "%s", buf);

		if (++n == 3) {
			nl_dump(p, "\n");
			nl_dump_line(p, "      ");
			n = 0;
		} else
			nl_dump(p, "  ");
	}

	if (n != 0)
		nl_dump(p, "\n");
}