static void
get_flags_sync_cb (struct nl_object *obj, void *arg)
{
	GetFlagsInfo *info = arg;

	/* Ensure this cache item matches our filter */
	if (nl_object_match_filter (obj, OBJ_CAST (info->filter)) != 0)
		info->flags = rtnl_link_get_flags ((struct rtnl_link *) obj);
}
Exemple #2
0
// Tests if the flags are set on the link. Returns None if the link is
// not found.
inline Result<bool> test(const std::string& _link, unsigned int flags)
{
  Result<Netlink<struct rtnl_link>> link = get(_link);
  if (link.isError()) {
    return Error(link.error());
  } else if (link.isNone()) {
    return None();
  }

  return flags == (rtnl_link_get_flags(link.get().get()) & flags);
}
bool devEthernet::hasLink() {
	if ( ! _netlinkSocket ) {
		MOD_ERROR("hasLink() called on uninitialized netlink socket.");
		return false;
	}

	nl_cache* cache;
	if ( rtnl_link_alloc_cache (_netlinkSocket, AF_UNSPEC, &cache) ) {
		MOD_ERROR("hasLink() rtnl_link_alloc_cache error: %s",
			nl_geterror(errno));
		return false;
	}

	rtnl_link* link = rtnl_link_get(cache, index());
	if ( ! link ) {
		MOD_ERROR("hasLink() rtnl_link_get error: %s", nl_geterror(errno));
			nl_cache_free(cache);
		return false;
	}

	// First, check that interface is able to send
	uint8_t operState = rtnl_link_get_operstate(link);

	#ifdef DEFINE_DEBUG
	char buf[100];
	rtnl_link_operstate2str (operState, buf, 100);
	MOD_DEBUG("operState is 0x%x (%s).", operState, buf);
	#endif

	bool ret = false;

	// Next make sure there's a carrier
	#ifndef IFF_LOWER_UP
	const int IFF_LOWER_UP = 0x10000;
	#endif

	#ifndef IFF_DORMANT
	const int IFF_DORMANT = 0x20000;
	#endif

	if ( operState == OperUp) {
		unsigned int flags = rtnl_link_get_flags (link);
		ret = ( ((flags & IFF_LOWER_UP) == IFF_LOWER_UP) && ((flags & IFF_DORMANT) != IFF_DORMANT) );
	}

	rtnl_link_put(link);
	nl_cache_free(cache);

	return ret;
}
static void
iface_mon_handler2(struct nl_object *obj, void *arg)
{
    struct rtnl_link *filter;
    struct rtnl_link *link_obj;
    int flags, up;
    char *ifname;
    iface_mon_cb cb = (iface_mon_cb)arg;

    filter = rtnl_link_alloc();
    if (!filter) {
        fprintf(stderr, "error allocating filter\n");
        return;
    }

    if (nl_object_match_filter (obj, OBJ_CAST (filter)) == 0) {
        rtnl_link_put(filter);
        return;
    }

    link_obj = (struct rtnl_link *) obj;
    flags = rtnl_link_get_flags (link_obj);
    ifname = rtnl_link_get_name(link_obj);

    /*
     * You can't bind a PF_PACKET socket to an interface that's not
     * up, so an interface going down is an "interface should be
     * removed" indication.
     *
     * XXX - what indication, if any, do we get if the interface
     * *completely goes away*?
     *
     * XXX - can we get events if an interface's link-layer or
     * network addresses change?
     */
    up = (flags & IFF_UP) ? 1 : 0;

    cb(ifname, up);

    rtnl_link_put(filter);

    return;
}
static void
link_msg_handler (struct nl_object *obj, void *arg)
{
	NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg);
	struct rtnl_link *filter;
	struct rtnl_link *link_obj;
	guint flags;
	guint ifidx;

	filter = rtnl_link_alloc ();
	if (!filter) {
		log_error_limited (self, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC,
		                   _("error processing netlink message: %s"),
		                   nl_geterror (ENOMEM));
		return;
	}

	/* Ensure it's a link object */
	if (nl_object_match_filter (obj, OBJ_CAST (filter)) == 0) {
		rtnl_link_put (filter);
		return;
	}

	link_obj = (struct rtnl_link *) obj;
	flags = rtnl_link_get_flags (link_obj);
	ifidx = rtnl_link_get_ifindex (link_obj);

	nm_log_dbg (LOGD_HW, "netlink link message: iface idx %d flags 0x%X", ifidx, flags);

	/* IFF_LOWER_UP is the indicator of carrier status since kernel commit
	 * b00055aacdb172c05067612278ba27265fcd05ce in 2.6.17.
	 */
	if (flags & IFF_LOWER_UP)
		g_signal_emit (self, signals[CARRIER_ON], 0, ifidx);
	else
		g_signal_emit (self, signals[CARRIER_OFF], 0, ifidx);

	rtnl_link_put (filter);
}
Exemple #6
0
static void
_j4status_nl_section_update(J4statusNlSection *self)
{
    if ( self->link == NULL )
        return;

    guint flags;
    flags = rtnl_link_get_flags(self->link);

    gchar *value = NULL;
    J4statusState state = J4STATUS_STATE_NO_STATE;
    if ( flags & IFF_LOWER_UP )
    {
        if ( ( self->ipv4_addresses == NULL ) && ( self->ipv6_addresses == NULL ) )
        {
            state = J4STATUS_STATE_AVERAGE;
            value = g_strdup("Connecting");
        }
        else
        {
            gchar *addresses;
            addresses = _j4status_nl_section_get_addresses(self);

            state = J4STATUS_STATE_GOOD;
            value = j4status_format_string_replace(self->context->formats.up, _j4status_nl_format_up_callback, addresses);

            g_free(addresses);
        }
    }
    else if ( flags & (IFF_UP | IFF_RUNNING) )
    {
        state = J4STATUS_STATE_BAD;
        value = g_strdup("Not connected");
        _j4status_nl_section_free_addresses(self);
    }

    j4status_section_set_state(self->section, state);
    j4status_section_set_value(self->section, value);
}
Exemple #7
0
// Sets the flags on the link. Returns false if the link is not found.
inline Try<bool> set(const std::string& _link, unsigned int flags)
{
  Result<Netlink<struct rtnl_link>> link = get(_link);
  if (link.isError()) {
    return Error(link.error());
  } else if (link.isNone()) {
    return false;
  }

  // TODO(jieyu): We use ioctl to set the flags because the interfaces
  // in libnl have some issues with virtual devices.
  struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));

  // Get the existing flags and take a bit-wise OR.
  ifr.ifr_flags = (rtnl_link_get_flags(link.get().get()) | flags);

  strncpy(ifr.ifr_name, _link.c_str(), IFNAMSIZ);

  int fd = ::socket(AF_INET, SOCK_STREAM, 0);
  if (fd == -1) {
    return ErrnoError();
  }

  if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
    if (errno == ENODEV) {
      os::close(fd);
      return false;
    } else {
      // Save the error string as os::close may overwrite errno.
      const std::string message = os::strerror(errno);
      os::close(fd);
      return Error(message);
    }
  }

  return true;
}
Exemple #8
0
TError TNl::OpenLinks(std::vector<std::shared_ptr<TNlLink>> &links, bool all) {
    struct nl_cache *cache;
    int ret;

    ret = rtnl_link_alloc_cache(GetSock(), AF_UNSPEC, &cache);
    if (ret < 0)
        return Error(ret, "Cannot allocate link cache");

    for (auto obj = nl_cache_get_first(cache); obj;
            obj = nl_cache_get_next(obj)) {
        auto link = (struct rtnl_link *)obj;

        if (!all && ((rtnl_link_get_flags(link) &
                        (IFF_LOOPBACK | IFF_RUNNING)) != IFF_RUNNING))
            continue;

        auto l = std::make_shared<TNlLink>(shared_from_this(), link);
        links.push_back(l);
    }

    nl_cache_free(cache);

    return TError::Success();
}
Exemple #9
0
/*
 * Called by nl_cache_mngr_data_ready if a link object changed.
 *
 * Sends a port status message to the controller.
 */
static void
link_change_cb(struct nl_cache *cache,
               struct nl_object *obj,
               int action,
               void *arg)
{
    struct rtnl_link *link = (struct rtnl_link *) obj;
    const char *ifname = rtnl_link_get_name(link);
    int ifflags = rtnl_link_get_flags(link);

    /*
     * Ignore additions/deletions, already handled by
     * ind_ovs_handle_vport_multicast.
     */
    if (action != NL_ACT_CHANGE) {
        return;
    }

    /* Ignore interfaces not connected to our datapath. */
    struct ind_ovs_port *port = ind_ovs_port_lookup_by_name(ifname);
    if (port == NULL) {
        return;
    }

    /* Log at INFO only if the interface transitioned between up/down */
    if ((ifflags & IFF_UP) && !(port->ifflags & IFF_UP)) {
        LOG_INFO("Interface %s state changed to up", ifname);
    } else if (!(ifflags & IFF_UP) && (port->ifflags & IFF_UP)) {
        LOG_INFO("Interface %s state changed to down", ifname);
    }

    LOG_VERBOSE("Sending port status change notification for interface %s", ifname);

    port->ifflags = ifflags;
    port_status_notify(port->dp_port_no, OF_PORT_CHANGE_REASON_MODIFY);
}
Exemple #10
0
static void nl_obj_input(struct nl_object *obj, void *arg)
{
	struct _obj
	{
		NLHDR_COMMON
	};

	struct _obj *o = (struct _obj *)obj;

	if( o->ce_msgtype == RTM_NEWLINK  || o->ce_msgtype == RTM_DELLINK ) 
	{
		struct rtnl_link *link = (struct rtnl_link *)obj;
		struct nl_addr *a = rtnl_link_get_addr(link);
		char buf[123];
		nl_addr2str(a, buf, sizeof(buf));
		int ifindex = rtnl_link_get_ifindex(link);
		bool active = rtnl_link_get_flags(link) & IFF_UP;
		char *iface = rtnl_link_get_name(link);
		if( o->ce_msgtype == RTM_NEWLINK ) 
		{
			struct link_addr *nla = g_hash_table_lookup(nl_runtime.link_addr_cache, &ifindex);
			if( nla == NULL )
			{
				g_critical("LINK NEW %s %i", iface, ifindex);
				struct link_addr *nla = link_addr_new(iface, ifindex, active);
				g_hash_table_insert(nl_runtime.link_addr_cache, &nla->ifindex, nla);
			}else
			{
				g_critical("LINK CHANGE %s %i", iface, ifindex);
				GHashTableIter iter;
				gpointer key, value;
				g_hash_table_iter_init(&iter, nla->addrs);
				if( active != nla->active )
				{
					while( g_hash_table_iter_next(&iter, &key, &value) )
					{
						struct incident *i;
						if( active )
						{
							g_critical("LINK UP");
							i = incident_new("dionaea.module.nl.addr.new");
						}else
						{
							g_critical("LINK DOWN");
							i = incident_new("dionaea.module.nl.addr.del");
						}
						incident_value_string_set(i, "addr", g_string_new(key));
						incident_value_string_set(i, "iface", g_string_new(nla->iface));
						incident_value_int_set(i, "scope", nla->ifindex);
						incident_report(i);
						incident_free(i);
					}
					nla->active = active;
				}
			}
		}else
		if( o->ce_msgtype == RTM_DELLINK ) 
		{
			g_critical("LINK DEL %s %i", iface, ifindex);
			struct link_addr *nla = g_hash_table_lookup(nl_runtime.link_addr_cache, &ifindex);
			g_hash_table_remove(nl_runtime.link_addr_cache, &ifindex);
			link_addr_free(nla);
		}
	}else
	if( o->ce_msgtype == RTM_NEWADDR  || o->ce_msgtype == RTM_DELADDR ) 
	{
		char buf[128];
		struct rtnl_addr *addr = (struct rtnl_addr *)obj;
		struct nl_addr *a = rtnl_addr_get_local(addr);
		int ifindex = rtnl_addr_get_ifindex(addr);
		nl_addr2str(a, buf, 128);
		char *slash; 
		if( (slash = strstr(buf, "/")) != NULL)
			*slash = '\0';
		char *saddr = NULL;

		struct link_addr *nla = g_hash_table_lookup(nl_runtime.link_addr_cache, &ifindex);
		if( !nla )
			return;

		if( o->ce_msgtype == RTM_NEWADDR ) 
		{
			if( g_hash_table_lookup(nla->addrs, buf) == NULL )
			{
				g_warning("NEW ADDR %s!", buf);
				saddr = g_strdup(buf);
				g_hash_table_insert(nla->addrs, saddr, saddr);

				if( nla->active )
				{
					struct incident *i = incident_new("dionaea.module.nl.addr.new");
					incident_value_string_set(i, "addr", g_string_new(saddr));
					incident_value_string_set(i, "iface", g_string_new(nla->iface));
					incident_value_int_set(i, "scope", nla->ifindex);
					incident_report(i);
					incident_free(i);
				}
			}
		}else
		if( o->ce_msgtype == RTM_DELADDR )
		{
			if( ( saddr = g_hash_table_lookup(nla->addrs, buf) ) != NULL )
			{
				g_warning("DEL ADDR! %s", buf);
				if( nla->active )
				{
					struct incident *i = incident_new("dionaea.module.nl.addr.del");
					incident_value_string_set(i, "addr", g_string_new(saddr));
					incident_value_string_set(i, "iface", g_string_new(nla->iface));
					incident_value_int_set(i, "scope", nla->ifindex);
					incident_report(i);
					incident_free(i);
				}
				g_hash_table_remove(nla->addrs, buf);
				g_free(saddr);
			}
		}
	}
/*
	struct nl_dump_params dp = {
		.dp_type = NL_DUMP_STATS,
		.dp_fd = stdout,
		.dp_dump_msgtype = 1,
	};

	nl_object_dump(obj, &dp);

	struct nl_dump_params params = {
		.dp_type = NL_DUMP_LINE,
		.dp_fd = stdout,
		.dp_prefix = 1,
	};
	g_debug("addr cache");
	nl_cache_dump(nl_runtime.addr_cache, &params);
	g_debug("arp cache");
	nl_cache_dump(nl_runtime.neigh_cache, &params);
	g_debug("link cache");
	nl_cache_dump(nl_runtime.link_cache, &params);
*/
}
Exemple #11
0
bool TNlLink::IsRunning() const {
    return rtnl_link_get_flags(Link) & IFF_RUNNING;
}
Exemple #12
0
bool TNlLink::IsLoopback() const {
    return rtnl_link_get_flags(Link) & IFF_LOOPBACK;
}
Exemple #13
0
static void handle_class(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "class", rdata)))
		return;

	ndata.parent = e;

	if (!strcmp(rtnl_tc_get_kind(tc), "htb"))
		element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc));

	find_classes(rtnl_tc_get_handle(tc), &ndata);
	find_qdiscs(rtnl_tc_get_handle(tc), &ndata);
}

static void find_qdiscs(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_qdisc *filter;

	if (!(filter = rtnl_qdisc_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter),
				handle_qdisc, rdata);

	rtnl_qdisc_put(filter);
}

static void find_cls(int ifindex, uint32_t parent, struct rdata *rdata)
{
	struct nl_cache *cls_cache;

	if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0)
		return;

	nl_cache_foreach(cls_cache, handle_cls, rdata);

	nl_cache_free(cls_cache);
}

static void find_classes(uint32_t parent, struct rdata *rdata)
{
	struct rtnl_class *filter;

	if (!(filter = rtnl_class_alloc()))
		return;

	rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);

	nl_cache_foreach_filter(class_cache, OBJ_CAST(filter),
				handle_class, rdata);

	rtnl_class_put(filter);
}

static void handle_qdisc(struct nl_object *obj, void *arg)
{
	struct rtnl_tc *tc = (struct rtnl_tc *) obj;
	struct element *e;
	struct rdata *rdata = arg;
	struct rdata ndata = {
		.level = rdata->level + 1,
	};

	if (!(e = handle_tc_obj(tc, "qdisc", rdata)))
		return;

	ndata.parent = e;

	find_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata);

	if (rtnl_tc_get_parent(tc) == TC_H_ROOT) {
		find_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT, &ndata);
		find_classes(TC_H_ROOT, &ndata);
	}

	find_classes(rtnl_tc_get_handle(tc), &ndata);
}

static void handle_tc(struct element *e, struct rtnl_link *link)
{
	struct rtnl_qdisc *qdisc;
	int ifindex = rtnl_link_get_ifindex(link);
	struct rdata rdata = {
		.level = 1,
		.parent = e,
	};

	if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0)
		return;

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS);
	if (qdisc) {
		handle_qdisc(OBJ_CAST(qdisc), &rdata);
		rtnl_qdisc_put(qdisc);
	}

	nl_cache_free(class_cache);
}

static void update_link_infos(struct element *e, struct rtnl_link *link)
{
	char buf[64];

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_mtu(link));
	element_update_info(e, "MTU", buf);

	rtnl_link_flags2str(rtnl_link_get_flags(link), buf, sizeof(buf));
	element_update_info(e, "Flags", buf);

	rtnl_link_operstate2str(rtnl_link_get_operstate(link),
				buf, sizeof(buf));
	element_update_info(e, "Operstate", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_ifindex(link));
	element_update_info(e, "IfIndex", buf);

	nl_addr2str(rtnl_link_get_addr(link), buf, sizeof(buf));
	element_update_info(e, "Address", buf);

	nl_addr2str(rtnl_link_get_broadcast(link), buf, sizeof(buf));
	element_update_info(e, "Broadcast", buf);

	rtnl_link_mode2str(rtnl_link_get_linkmode(link),
			   buf, sizeof(buf));
	element_update_info(e, "Mode", buf);

	snprintf(buf, sizeof(buf), "%u", rtnl_link_get_txqlen(link));
	element_update_info(e, "TXQlen", buf);

	nl_af2str(rtnl_link_get_family(link), buf, sizeof(buf));
	element_update_info(e, "Family", buf);

	element_update_info(e, "Alias",
		rtnl_link_get_ifalias(link) ? : "");

	element_update_info(e, "Qdisc",
		rtnl_link_get_qdisc(link) ? : "");

	if (rtnl_link_get_link(link)) {
		snprintf(buf, sizeof(buf), "%u", rtnl_link_get_link(link));
		element_update_info(e, "SlaveOfIndex", buf);
	}
}

static void do_link(struct nl_object *obj, void *arg)
{
	struct rtnl_link *link = (struct rtnl_link *) obj;
	struct element *e, *e_parent = NULL;
	int i, master_ifindex;

	if (!cfg_show_all && !(rtnl_link_get_flags(link) & IFF_UP)) {
		/* FIXME: delete element */
		return;
	}

	/* Check if the interface is a slave of another interface */
	if ((master_ifindex = rtnl_link_get_link(link))) {
		char parent[IFNAMSIZ+1];

		rtnl_link_i2name(link_cache, master_ifindex,
				 parent, sizeof(parent));

		e_parent = element_lookup(grp, parent, master_ifindex, NULL, 0);
	}

	if (!(e = element_lookup(grp, rtnl_link_get_name(link),
				 rtnl_link_get_ifindex(link), e_parent, ELEMENT_CREAT)))
		return;

	if (e->e_flags & ELEMENT_FLAG_CREATED) {
		if (e->e_parent)
			e->e_level = e->e_parent->e_level + 1;

		if (element_set_key_attr(e, "bytes", "packets") ||
		    element_set_usage_attr(e, "bytes"))
			BUG();

		/* FIXME: Update link infos every 1s or so */
		update_link_infos(e, link);

		e->e_flags &= ~ELEMENT_FLAG_CREATED;
	}

	for (i = 0; i < ARRAY_SIZE(link_attrs); i++) {
		struct attr_map *m = &link_attrs[i];
		uint64_t c_rx = 0, c_tx = 0;
		int flags = 0;

		if (m->rxid >= 0) {
			c_rx = rtnl_link_get_stat(link, m->rxid);
			flags |= UPDATE_FLAG_RX;
		}

		if (m->txid >= 0) {
			c_tx = rtnl_link_get_stat(link, m->txid);
			flags |= UPDATE_FLAG_TX;
		}

		attr_update(e, m->attrid, c_rx, c_tx, flags);
	}

	if (!c_notc)
		handle_tc(e, link);

	element_notify_update(e, NULL);
	element_lifesign(e, 1);
}

static void netlink_read(void)
{
	int err;

	if ((err = nl_cache_resync(sock, link_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync link cache: %s\n", nl_geterror(err));
		goto disable;
	}

	if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
		fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err));
		goto disable;
	}

	nl_cache_foreach(link_cache, do_link, NULL);

	return;

disable:
	netlink_ops.m_flags &= ~BMON_MODULE_ENABLED;
}

static void netlink_shutdown(void)
{
	nl_cache_free(link_cache);
	nl_cache_free(qdisc_cache);
	nl_socket_free(sock);
}