예제 #1
0
static int sample_nl_cb(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct nlattr *attrs_echo[SAMPLE_ECHO_ATTR_MAX + 1];
	struct nlattr *attrs_info[SAMPLE_INFO_ATTR_MAX + 1];
	struct sample_nla sn;


	if (genlmsg_parse(nlh, 0, attrs_echo, SAMPLE_ECHO_ATTR_MAX,
				sample_echo_policy) != 0){
		return -1;
	}

	if (!attrs_echo[SAMPLE_ECHO_ATTR_INFO] || !attrs_echo[SAMPLE_ECHO_ATTR_DATA]){
		elog("attrs null\n");
		return -1;
	}

	strncpy(sn.data, nla_get_string(attrs_echo[SAMPLE_ECHO_ATTR_DATA]), sizeof(sn.data));

	if(nla_parse_nested(attrs_info, SAMPLE_INFO_ATTR_MAX, 
				attrs_echo[SAMPLE_ECHO_ATTR_INFO], sample_info_policy))
		return -1;

	sn.info.x = nla_get_u32(attrs_info[SAMPLE_INFO_ATTR_X]);
	sn.info.y = nla_get_u32(attrs_info[SAMPLE_INFO_ATTR_Y]);
	sample_nl_dump(&sn);
	return NL_OK;
}
// valid interface callback handler
static int iface_handler(struct nl_msg *msg, void *arg)
{
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];

	nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);

	if (tb_msg[NL80211_ATTR_WIPHY])
	{
		char wiphy[IFNAMSIZ];
		sprintf(wiphy, "phy%d", nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]));

		// If selected physical interface matches the result, search for a monitor interface and copy the name
		if(strcmp(phy_name, wiphy) == 0)
		{
			if (tb_msg[NL80211_ATTR_IFTYPE] && tb_msg[NL80211_ATTR_IFNAME])
			{
				// If the interface type is monitor
				if(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]) == 6)
					strcpy(IF_name, nla_get_string(tb_msg[NL80211_ATTR_IFNAME]));
			}
		}
	}

	return NL_SKIP;
}
예제 #3
0
파일: netlink.c 프로젝트: aklein53/neard
static int get_devices_handler(struct nl_msg *n, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(n);
	struct nlattr *attrs[NFC_ATTR_MAX + 1];
	char *name;
	uint32_t idx, protocols;
	bool powered;

	DBG("");

	genlmsg_parse(nlh, 0, attrs, NFC_ATTR_MAX, NULL);

	if (!attrs[NFC_ATTR_DEVICE_INDEX] ||
	    !attrs[NFC_ATTR_DEVICE_NAME] ||
	    !attrs[NFC_ATTR_PROTOCOLS]) {
		nl_perror(NLE_MISSING_ATTR, "NFC_CMD_GET_DEVICE");
		return NL_STOP;
	}

	idx = nla_get_u32(attrs[NFC_ATTR_DEVICE_INDEX]);
	name = nla_get_string(attrs[NFC_ATTR_DEVICE_NAME]);
	protocols = nla_get_u32(attrs[NFC_ATTR_PROTOCOLS]);

	if (!attrs[NFC_ATTR_DEVICE_POWERED])
		powered = false;
	else
		powered = nla_get_u8(attrs[NFC_ATTR_DEVICE_POWERED]);

	__near_manager_adapter_add(idx, name, protocols, powered);

	return NL_SKIP;
}
예제 #4
0
파일: libipvs.c 프로젝트: Am1GO/keepalived
static int ipvs_daemon_parse_cb(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
	struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1];
	ipvs_daemon_t *u = (ipvs_daemon_t *)arg;
	int i = 0;

	/* We may get two daemons.  If we've already got one, this is the second */
	if (u[0].state)
		i = 1;

	if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
		return -1;

	if (nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX,
			     attrs[IPVS_CMD_ATTR_DAEMON], ipvs_daemon_policy))
		return -1;

	if (!(daemon_attrs[IPVS_DAEMON_ATTR_STATE] &&
	      daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
	      daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
		return -1;

	u[i].state = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_STATE]);
	strncpy(u[i].mcast_ifn,
		nla_get_string(daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
		IP_VS_IFNAME_MAXLEN);
	u[i].syncid = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]);

	return NL_OK;
}
예제 #5
0
static int _list(struct nl_msg *nl_msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(nl_msg);
	struct nlattr *info[TIPC_NLA_MAX + 1];
	struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];

	genlmsg_parse(nlh, 0, info, TIPC_NLA_MAX, NULL);

	if (!info[TIPC_NLA_BEARER]) {
		log_err("no bearer received from kernel\n");
		return NL_STOP;
	}

	if (nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
			     info[TIPC_NLA_BEARER], NULL)) {
		log_err("parsing nested bearer properties\n");
		return NL_STOP;
	}

	if (!attrs[TIPC_NLA_BEARER_NAME]) {
		log_err("no bearer name received from kernel\n");
		return NL_STOP;
	}

	printf("%s\n", nla_get_string(attrs[TIPC_NLA_BEARER_NAME]));

	return NL_OK;
}
예제 #6
0
파일: libipvs.c 프로젝트: Crazykev/ipvsadm
static int ipvs_daemon_parse_cb(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
	struct nlattr *daemon_attrs[IPVS_DAEMON_ATTR_MAX + 1];
	ipvs_daemon_t *u = (ipvs_daemon_t *)arg;
	struct nlattr *a;
	int i = 0;

	/* We may get two daemons.  If we've already got one, this is the second */
	if (u[0].state)
		i = 1;

	if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
		return -1;

	if (nla_parse_nested(daemon_attrs, IPVS_DAEMON_ATTR_MAX,
			     attrs[IPVS_CMD_ATTR_DAEMON], ipvs_daemon_policy))
		return -1;

	if (!(daemon_attrs[IPVS_DAEMON_ATTR_STATE] &&
	      daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
	      daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
		return -1;

	u[i].state = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_STATE]);
	strncpy(u[i].mcast_ifn,
		nla_get_string(daemon_attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
		IP_VS_IFNAME_MAXLEN);
	u[i].syncid = nla_get_u32(daemon_attrs[IPVS_DAEMON_ATTR_SYNC_ID]);

	a = daemon_attrs[IPVS_DAEMON_ATTR_SYNC_MAXLEN];
	if (a)
		u[i].sync_maxlen = nla_get_u16(a);

	a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_PORT];
	if (a)
		u[i].mcast_port = nla_get_u16(a);

	a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_TTL];
	if (a)
		u[i].mcast_ttl = nla_get_u8(a);

	a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_GROUP];
	if (a) {
		u[i].mcast_af = AF_INET;
		u[i].mcast_group.ip = nla_get_u32(a);
	} else {
		a = daemon_attrs[IPVS_DAEMON_ATTR_MCAST_GROUP6];
		if (a) {
			u[i].mcast_af = AF_INET6;
			memcpy(&u[i].mcast_group.in6, nla_data(a),
			       sizeof(u[i].mcast_group.in6));
		}
	}

	return NL_OK;
}
예제 #7
0
static iz_res_t list_response(struct iz_cmd *cmd, struct genlmsghdr *ghdr, struct nlattr **attrs)
{
	char * dev_name;
	char * phy_name = NULL;
	uint32_t dev_index;
	unsigned char hw_addr[IEEE802154_ADDR_LEN];
	uint16_t short_addr;
	uint16_t pan_id;
	char * dev_type_str;

	/* Check for mandatory attributes */
	if (!attrs[IEEE802154_ATTR_DEV_NAME]     ||
	    !attrs[IEEE802154_ATTR_DEV_INDEX]    ||
	    !attrs[IEEE802154_ATTR_HW_ADDR]      ||
	    !attrs[IEEE802154_ATTR_SHORT_ADDR]   ||
	    !attrs[IEEE802154_ATTR_PAN_ID])
		return IZ_STOP_ERR;

	/* Get attribute values from the message */
	dev_name = nla_get_string(attrs[IEEE802154_ATTR_DEV_NAME]);
	dev_index = nla_get_u32(attrs[IEEE802154_ATTR_DEV_INDEX]);
	nla_memcpy(hw_addr, attrs[IEEE802154_ATTR_HW_ADDR],
		IEEE802154_ADDR_LEN);
	short_addr = nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]);
	pan_id = nla_get_u16(attrs[IEEE802154_ATTR_PAN_ID]);

	if (attrs[IEEE802154_ATTR_PHY_NAME])
		phy_name = nla_get_string(attrs[IEEE802154_ATTR_PHY_NAME]);

	/* Display information about interface */
	printf("%s\n", dev_name);
	dev_type_str = "IEEE 802.15.4 MAC interface";
	printf("    link: %s\n", dev_type_str);
	if (phy_name)
		printf("    phy %s\n", phy_name);

	printf("    hw %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
			hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3],
			hw_addr[4], hw_addr[5], hw_addr[6], hw_addr[7]);
	printf(" pan 0x%04hx short 0x%04hx\n", pan_id, short_addr);

	return (cmd->flags & NLM_F_MULTI) ? IZ_CONT_OK : IZ_STOP_OK;
}
예제 #8
0
static int get_ifinfo_cb(struct nl_msg *msg, void *arg)
{
	struct nlt_ifinfo *ifinfo = (struct nlt_ifinfo *) arg;

	struct nlt_msg r;
	nlt_parse(msg, &r);


	if (r.cmd != NL80211_CMD_NEW_INTERFACE)
		return NL_OK;


	if (ifinfo->ifname != NULL) {
		printf("! if info != 0\n");

		if (!r.attribs[NL80211_ATTR_IFNAME])
			return NL_OK;

		const char *cbname = nla_get_string(r.attribs[NL80211_ATTR_IFNAME]);
		printf("Callback name %s\n", cbname);

		if (strcmp(ifinfo->ifname, nla_get_string(r.attribs[NL80211_ATTR_IFNAME]))
		    != 0)
			return NL_OK;
	}


	if (r.attribs[NL80211_ATTR_IFNAME]) {
		if (ifinfo->ifname == NULL)
			ifinfo->ifname = strdup(nla_get_string(r.attribs[NL80211_ATTR_IFNAME]));
	}

	if (r.attribs[NL80211_ATTR_IFINDEX])
		ifinfo->ifindex = nla_get_u32(r.attribs[NL80211_ATTR_IFINDEX]);

	if (r.attribs[NL80211_ATTR_IFTYPE])
		ifinfo->iftype = nla_get_u32(r.attribs[NL80211_ATTR_IFTYPE]);



	return NL_OK;
}
예제 #9
0
static int print_iface_handler(struct nl_msg *msg, void *arg)
{
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *tb_msg[NL802154_ATTR_MAX + 1];
	unsigned int *wpan_phy = arg;
	const char *indent = "";

	nla_parse(tb_msg, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (wpan_phy && tb_msg[NL802154_ATTR_WPAN_PHY]) {
		unsigned int thiswpan_phy = nla_get_u32(tb_msg[NL802154_ATTR_WPAN_PHY]);
		indent = "\t";
		if (*wpan_phy != thiswpan_phy)
			printf("phy#%d\n", thiswpan_phy);
		*wpan_phy = thiswpan_phy;
	}

	if (tb_msg[NL802154_ATTR_IFNAME])
		printf("%sInterface %s\n", indent, nla_get_string(tb_msg[NL802154_ATTR_IFNAME]));
	else
		printf("%sUnnamed/non-netdev interface\n", indent);

	if (tb_msg[NL802154_ATTR_IFINDEX])
		printf("%s\tifindex %d\n", indent, nla_get_u32(tb_msg[NL802154_ATTR_IFINDEX]));
	if (tb_msg[NL802154_ATTR_WPAN_DEV])
		printf("%s\twpan_dev 0x%llx\n", indent,
		       (unsigned long long)nla_get_u64(tb_msg[NL802154_ATTR_WPAN_DEV]));
	if (tb_msg[NL802154_ATTR_EXTENDED_ADDR])
		printf("%s\textended_addr 0x%016" PRIx64 "\n", indent,
		       le64toh(nla_get_u64(tb_msg[NL802154_ATTR_EXTENDED_ADDR])));
	if (tb_msg[NL802154_ATTR_SHORT_ADDR])
		printf("%s\tshort_addr 0x%04x\n", indent,
		       le16toh(nla_get_u16(tb_msg[NL802154_ATTR_SHORT_ADDR])));
	if (tb_msg[NL802154_ATTR_PAN_ID])
		printf("%s\tpan_id 0x%04x\n", indent,
		       le16toh(nla_get_u16(tb_msg[NL802154_ATTR_PAN_ID])));
	if (tb_msg[NL802154_ATTR_IFTYPE])
		printf("%s\ttype %s\n", indent, iftype_name(nla_get_u32(tb_msg[NL802154_ATTR_IFTYPE])));
	if (tb_msg[NL802154_ATTR_MAX_FRAME_RETRIES])
		printf("%s\tmax_frame_retries %d\n", indent, nla_get_s8(tb_msg[NL802154_ATTR_MAX_FRAME_RETRIES]));
	if (tb_msg[NL802154_ATTR_MIN_BE])
		printf("%s\tmin_be %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_MIN_BE]));
	if (tb_msg[NL802154_ATTR_MAX_BE])
		printf("%s\tmax_be %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_MAX_BE]));
	if (tb_msg[NL802154_ATTR_MAX_CSMA_BACKOFFS])
		printf("%s\tmax_csma_backoffs %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_MAX_CSMA_BACKOFFS]));
	if (tb_msg[NL802154_ATTR_LBT_MODE])
		printf("%s\tlbt %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_LBT_MODE]));
	if (tb_msg[NL802154_ATTR_ACKREQ_DEFAULT])
		printf("%s\tackreq_default %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_ACKREQ_DEFAULT]));

	return NL_SKIP;
}
예제 #10
0
static int cb_handler(struct nl_msg * msg, void * arg)
{

  * (int*) arg = 123; // cbarg

  struct nlmsghdr * hdr = nlmsg_hdr(msg);
  struct genlmsghdr * gnlh = nlmsg_data(hdr);

  int valid =
    genlmsg_validate(hdr, 0, DEMO_ATTR_MAX, demo_gnl_policy);
  printf("valid %d %s\n", valid, valid ? "ERROR" : "OK");

  // one way
  struct nlattr * attrs[DEMO_ATTR_MAX + 1];

  if (genlmsg_parse(hdr, 0, attrs, DEMO_ATTR_MAX, demo_gnl_policy) < 0)
    {
      printf("genlsmg_parse ERROR\n");
    }

  else
    {
      printf("genlsmg_parse OK\n");
      printf("attr1 %s\n", nla_get_string(attrs[DEMO_ATTR1_STRING]));
      printf("attr2 %x\n", nla_get_u16(attrs[DEMO_ATTR2_UINT16]));
      struct attr_custom * cp = (struct attr_custom *) nla_data(attrs[DEMO_ATTR3_CUSTOM]);
      printf("attr3 %d %ld %f %lf\n", cp->a, cp->b, cp->c,cp->d);

    }

  // another way
  printf("gnlh->cmd %d\n", gnlh->cmd);	//--- DEMO_CMD_ECHO

  int remaining = genlmsg_attrlen(gnlh, 0);
  struct nlattr * attr = genlmsg_attrdata(gnlh, 0);

  while (nla_ok(attr, remaining))
    {
      printf("remaining %d\n", remaining);
      printf("attr @ %p\n", attr); // nla_get_string(attr)
      attr = nla_next(attr, &remaining);
    }

  nl_msg_dump(msg, stderr);

  return NL_STOP;
}
예제 #11
0
파일: info.c 프로젝트: agx/wpan-tools
static int print_phy_handler(struct nl_msg *msg, void *arg)
{
	struct nlattr *tb_msg[NL802154_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	int rem_page, i, ret;
	int64_t phy_id = -1;
	bool print_name = true;
	struct nlattr *nl_page;
	enum nl802154_cca_modes cca_mode;

	nla_parse(tb_msg, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (tb_msg[NL802154_ATTR_WPAN_PHY]) {
		if (nla_get_u32(tb_msg[NL802154_ATTR_WPAN_PHY]) == phy_id)
			print_name = false;
		phy_id = nla_get_u32(tb_msg[NL802154_ATTR_WPAN_PHY]);
	}
	if (print_name && tb_msg[NL802154_ATTR_WPAN_PHY_NAME])
		printf("wpan_phy %s\n", nla_get_string(tb_msg[NL802154_ATTR_WPAN_PHY_NAME]));

	/* TODO remove this handling it's deprecated */
	if (tb_msg[NL802154_ATTR_CHANNELS_SUPPORTED]) {
		unsigned char page = 0;
		unsigned long channel;
		printf("supported channels:\n");
		nla_for_each_nested(nl_page,
				    tb_msg[NL802154_ATTR_CHANNELS_SUPPORTED],
				    rem_page) {
			channel = nla_get_u32(nl_page);
			if (channel) {
				printf("\tpage %d: ", page);
				for (i = 0; i <= 31; i++) {
					if (channel & 0x1)
						printf("%d,", i);
					channel >>= 1;
				}
				/* TODO hack use sprintf here */
				printf("\b \b\n");
			}
			page++;
		}
	}
예제 #12
0
static iz_res_t event_response(struct iz_cmd *cmd, struct genlmsghdr *ghdr, struct nlattr **attrs)
{
	const char *iface = nla_get_string(attrs[IEEE802154_ATTR_DEV_NAME]);

	if (cmd->argv[1] && (!iface || strcmp(cmd->argv[1], iface)))
		return IZ_CONT_OK;

	if (!iface)
		iface = "?????";

	if (ghdr->cmd < __IEEE802154_CMD_MAX)
		fprintf(stdout, "%s: %s (%i)\n", iface, iz_cmd_names[ghdr->cmd], ghdr->cmd);
	else
		fprintf(stdout, "%s: UNKNOWN (%i)\n", iface, ghdr->cmd);

	fflush(stdout);

	return IZ_CONT_OK;
}
예제 #13
0
파일: netlink.c 프로젝트: aklein53/neard
static int nfc_netlink_event_adapter(struct genlmsghdr *gnlh, bool add)
{
	struct nlattr *attrs[NFC_ATTR_MAX + 1];
	uint32_t idx;

	DBG("");

	nla_parse(attrs, NFC_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);
	if (!attrs[NFC_ATTR_DEVICE_INDEX]) {
		near_error("Missing device index");
		return -ENODEV;
	}

	idx = nla_get_u32(attrs[NFC_ATTR_DEVICE_INDEX]);

	if (add &&
		(!attrs[NFC_ATTR_DEVICE_NAME] ||
			!attrs[NFC_ATTR_PROTOCOLS])) {
		near_error("Missing attributes");
		return -EINVAL;
	}

	if (add) {
		char *name;
		uint32_t protocols;
		bool powered;

		name = nla_get_string(attrs[NFC_ATTR_DEVICE_NAME]);
		protocols = nla_get_u32(attrs[NFC_ATTR_PROTOCOLS]);
		if (!attrs[NFC_ATTR_DEVICE_POWERED])
			powered = false;
		else
			powered = nla_get_u8(attrs[NFC_ATTR_DEVICE_POWERED]);

		return __near_manager_adapter_add(idx, name,
						protocols, powered);
	} else {
		__near_manager_adapter_remove(idx);
	}

	return 0;
}
예제 #14
0
파일: vport.c 프로젝트: Sovietaced/ivs
static int
port_stats_iterator(struct nl_msg *msg, void *arg)
{
    of_list_port_stats_entry_t *list = arg;

    struct nlmsghdr *nlh = nlmsg_hdr(msg);
    struct nlattr *attrs[OVS_VPORT_ATTR_MAX+1];
    if (genlmsg_parse(nlh, sizeof(struct ovs_header),
                    attrs, OVS_VPORT_ATTR_MAX,
                    NULL) < 0) {
        abort();
    }
    assert(attrs[OVS_VPORT_ATTR_PORT_NO]);
    assert(attrs[OVS_VPORT_ATTR_STATS]);

    uint32_t port_no = nla_get_u32(attrs[OVS_VPORT_ATTR_PORT_NO]);
    char *ifname = nla_get_string(attrs[OVS_VPORT_ATTR_NAME]);
    uint32_t vport_type = nla_get_u32(attrs[OVS_VPORT_ATTR_TYPE]);
    struct ovs_vport_stats *port_stats = nla_data(attrs[OVS_VPORT_ATTR_STATS]);

    of_port_stats_entry_t entry[1];
    of_port_stats_entry_init(entry, list->version, -1, 1);
    if (of_list_port_stats_entry_append_bind(list, entry) < 0) {
        /* TODO needs fix in indigo core */
        LOG_ERROR("too many port stats replies");
        return NL_STOP;
    }

    of_port_stats_entry_port_no_set(entry, port_no);

    struct rtnl_link *link;
    if ((vport_type == OVS_VPORT_TYPE_NETDEV
        || vport_type == OVS_VPORT_TYPE_INTERNAL)
        && (link = rtnl_link_get_by_name(link_cache, ifname))) {
        /* Get interface stats from NETLINK_ROUTE */
        of_port_stats_entry_rx_packets_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_PACKETS));
        of_port_stats_entry_tx_packets_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_PACKETS));
        of_port_stats_entry_rx_bytes_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_BYTES));
        of_port_stats_entry_tx_bytes_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_BYTES));
        of_port_stats_entry_rx_dropped_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_DROPPED));
        of_port_stats_entry_tx_dropped_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_DROPPED));
        of_port_stats_entry_rx_errors_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_ERRORS));
        of_port_stats_entry_tx_errors_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_TX_ERRORS));
        of_port_stats_entry_rx_frame_err_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_FRAME_ERR));
        of_port_stats_entry_rx_over_err_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_OVER_ERR));
        of_port_stats_entry_rx_crc_err_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_RX_CRC_ERR));
        of_port_stats_entry_collisions_set(entry,
            rtnl_link_get_stat(link, RTNL_LINK_COLLISIONS));
        rtnl_link_put(link);
    } else {
        /* Use more limited stats from the datapath */
        of_port_stats_entry_rx_packets_set(entry, port_stats->rx_packets);
        of_port_stats_entry_tx_packets_set(entry, port_stats->tx_packets);
        of_port_stats_entry_rx_bytes_set(entry, port_stats->rx_bytes);
        of_port_stats_entry_tx_bytes_set(entry, port_stats->tx_bytes);
        of_port_stats_entry_rx_dropped_set(entry, port_stats->rx_dropped);
        of_port_stats_entry_tx_dropped_set(entry, port_stats->tx_dropped);
        of_port_stats_entry_rx_errors_set(entry, port_stats->rx_errors);
        of_port_stats_entry_tx_errors_set(entry, port_stats->tx_errors);
        of_port_stats_entry_rx_frame_err_set(entry, 0);
        of_port_stats_entry_rx_over_err_set(entry, 0);
        of_port_stats_entry_rx_crc_err_set(entry, 0);
        of_port_stats_entry_collisions_set(entry, 0);
    }

    return NL_OK;
}
static int print_iface_handler(struct nl_msg *msg, void *arg)
{
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
	unsigned int *wiphy = arg;
	const char *indent = "";

	nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (wiphy && tb_msg[NL80211_ATTR_WIPHY]) {
		unsigned int thiswiphy = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]);
		indent = "\t";
		if (*wiphy != thiswiphy)
			printf("phy#%d\n", thiswiphy);
		*wiphy = thiswiphy;
	}

	if (tb_msg[NL80211_ATTR_IFNAME])
		printf("%sInterface %s\n", indent, nla_get_string(tb_msg[NL80211_ATTR_IFNAME]));
	else
		printf("%sUnnamed/non-netdev interface\n", indent);
	if (tb_msg[NL80211_ATTR_IFINDEX])
		printf("%s\tifindex %d\n", indent, nla_get_u32(tb_msg[NL80211_ATTR_IFINDEX]));
	if (tb_msg[NL80211_ATTR_WDEV])
		printf("%s\twdev 0x%llx\n", indent,
		       (unsigned long long)nla_get_u64(tb_msg[NL80211_ATTR_WDEV]));
	if (tb_msg[NL80211_ATTR_MAC]) {
		char mac_addr[20];
		mac_addr_n2a(mac_addr, nla_data(tb_msg[NL80211_ATTR_MAC]));
		printf("%s\taddr %s\n", indent, mac_addr);
	}
	if (tb_msg[NL80211_ATTR_SSID]) {
		printf("%s\tssid ", indent);
		print_ssid_escaped(nla_len(tb_msg[NL80211_ATTR_SSID]),
				   nla_data(tb_msg[NL80211_ATTR_SSID]));
		printf("\n");
	}
	if (tb_msg[NL80211_ATTR_IFTYPE])
		printf("%s\ttype %s\n", indent, iftype_name(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE])));
	if (!wiphy && tb_msg[NL80211_ATTR_WIPHY])
		printf("%s\twiphy %d\n", indent, nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]));
	if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
		uint32_t freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);

		printf("%s\tchannel %d (%d MHz)", indent,
		       ieee80211_frequency_to_channel(freq), freq);

		if (tb_msg[NL80211_ATTR_CHANNEL_WIDTH]) {
			printf(", width: %s",
				channel_width_name(nla_get_u32(tb_msg[NL80211_ATTR_CHANNEL_WIDTH])));
			if (tb_msg[NL80211_ATTR_CENTER_FREQ1])
				printf(", center1: %d MHz",
					nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ1]));
			if (tb_msg[NL80211_ATTR_CENTER_FREQ2])
				printf(", center2: %d MHz",
					nla_get_u32(tb_msg[NL80211_ATTR_CENTER_FREQ2]));
		} else if (tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
			enum nl80211_channel_type channel_type;

			channel_type = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
			printf(" %s", channel_type_name(channel_type));
		}

		printf("\n");
	}

	return NL_SKIP;
}
static void copy_cacheinfo_into_route(struct rta_cacheinfo *ci,
				      struct rtnl_route *route)
{
	struct rtnl_rtcacheinfo nci = {
		.rtci_clntref  = ci->rta_clntref,
		.rtci_last_use = ci->rta_lastuse,
		.rtci_expires  = ci->rta_expires,
		.rtci_error    = ci->rta_error,
		.rtci_used     = ci->rta_used,
		.rtci_id       = ci->rta_id,
		.rtci_ts       = ci->rta_ts,
		.rtci_tsage    = ci->rta_tsage,
	};

	rtnl_route_set_cacheinfo(route, &nci);
}

static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
			    struct nlmsghdr *nlh, struct nl_parser_param *pp)
{
	struct rtmsg *rtm;
	struct rtnl_route *route;
	struct nlattr *tb[RTA_MAX + 1];
	struct nl_addr *src = NULL, *dst = NULL, *addr;
	int err;

	route = rtnl_route_alloc();
	if (!route) {
		err = nl_errno(ENOMEM);
		goto errout;
	}

	route->ce_msgtype = nlh->nlmsg_type;

	err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX,
			  route_policy);
	if (err < 0)
		goto errout;

	rtm = nlmsg_data(nlh);
	rtnl_route_set_family(route, rtm->rtm_family);
	rtnl_route_set_tos(route, rtm->rtm_tos);
	rtnl_route_set_table(route, rtm->rtm_table);
	rtnl_route_set_type(route, rtm->rtm_type);
	rtnl_route_set_scope(route, rtm->rtm_scope);
	rtnl_route_set_protocol(route, rtm->rtm_protocol);
	rtnl_route_set_flags(route, rtm->rtm_flags);

	if (tb[RTA_DST]) {
		dst = nla_get_addr(tb[RTA_DST], rtm->rtm_family);
		if (dst == NULL)
			goto errout_errno;
	} else {
		dst = nl_addr_alloc(0);
		nl_addr_set_family(dst, rtm->rtm_family);
	}

	nl_addr_set_prefixlen(dst, rtm->rtm_dst_len);
	err = rtnl_route_set_dst(route, dst);
	if (err < 0)
		goto errout;

	nl_addr_put(dst);

	if (tb[RTA_SRC]) {
		src = nla_get_addr(tb[RTA_SRC], rtm->rtm_family);
		if (src == NULL)
			goto errout_errno;
	} else if (rtm->rtm_src_len)
		src = nl_addr_alloc(0);

	if (src) {
		nl_addr_set_prefixlen(src, rtm->rtm_src_len);
		rtnl_route_set_src(route, src);
		nl_addr_put(src);
	}

	if (tb[RTA_IIF])
		rtnl_route_set_iif(route, nla_get_string(tb[RTA_IIF]));

	if (tb[RTA_OIF])
		rtnl_route_set_oif(route, nla_get_u32(tb[RTA_OIF]));

	if (tb[RTA_GATEWAY]) {
		addr = nla_get_addr(tb[RTA_GATEWAY], route->rt_family);
		if (addr == NULL)
			goto errout_errno;
		rtnl_route_set_gateway(route, addr);
		nl_addr_put(addr);
	}

	if (tb[RTA_PRIORITY])
		rtnl_route_set_prio(route, nla_get_u32(tb[RTA_PRIORITY]));

	if (tb[RTA_PREFSRC]) {
		addr = nla_get_addr(tb[RTA_PREFSRC], route->rt_family);
		if (addr == NULL)
			goto errout_errno;
		rtnl_route_set_pref_src(route, addr);
		nl_addr_put(addr);
	}

	if (tb[RTA_METRICS]) {
		struct nlattr *mtb[RTAX_MAX + 1];
		int i;

		err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL);
		if (err < 0)
			goto errout;

		for (i = 1; i <= RTAX_MAX; i++) {
			if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) {
				uint32_t m = nla_get_u32(mtb[i]);
				if (rtnl_route_set_metric(route, i, m) < 0)
					goto errout_errno;
			}
		}
	}

	if (tb[RTA_MULTIPATH]) {
		struct rtnl_nexthop *nh;
		struct rtnexthop *rtnh = nla_data(tb[RTA_MULTIPATH]);
		size_t tlen = nla_len(tb[RTA_MULTIPATH]);

		while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
			nh = rtnl_route_nh_alloc();
			if (!nh)
				goto errout;

			rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops);
			rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex);
			rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags);

			if (rtnh->rtnh_len > sizeof(*rtnh)) {
				struct nlattr *ntb[RTA_MAX + 1];
				nla_parse(ntb, RTA_MAX, (struct nlattr *)
					  RTNH_DATA(rtnh),
					  rtnh->rtnh_len - sizeof(*rtnh),
					  route_policy);

				if (ntb[RTA_GATEWAY]) {
					nh->rtnh_gateway = nla_get_addr(
							ntb[RTA_GATEWAY],
							route->rt_family);
					nh->rtnh_mask = NEXTHOP_HAS_GATEWAY;
				}
			}

			rtnl_route_add_nexthop(route, nh);
			tlen -= RTNH_ALIGN(rtnh->rtnh_len);
			rtnh = RTNH_NEXT(rtnh);
		}
	}

	if (tb[RTA_FLOW])
		rtnl_route_set_realms(route, nla_get_u32(tb[RTA_FLOW]));

	if (tb[RTA_CACHEINFO])
		copy_cacheinfo_into_route(nla_data(tb[RTA_CACHEINFO]), route);

	if (tb[RTA_MP_ALGO])
		rtnl_route_set_mp_algo(route, nla_get_u32(tb[RTA_MP_ALGO]));

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

	err = P_ACCEPT;

errout:
	rtnl_route_put(route);
	return err;

errout_errno:
	err = nl_get_errno();
	goto errout;
}

static int route_request_update(struct nl_cache *c, struct nl_handle *h)
{
	return nl_rtgen_request(h, RTM_GETROUTE, AF_UNSPEC, NLM_F_DUMP);
}

/**
 * @name Cache Management
 * @{
 */

/**
 * Build a route cache holding all routes currently configured in the kernel
 * @arg handle		netlink handle
 *
 * Allocates a new cache, initializes it properly and updates it to
 * contain all routes currently configured in the kernel.
 *
 * @note The caller is responsible for destroying and freeing the
 *       cache after using it.
 * @return The cache or NULL if an error has occured.
 */
struct nl_cache *rtnl_route_alloc_cache(struct nl_handle *handle)
{
	struct nl_cache *cache;

	cache = nl_cache_alloc(&rtnl_route_ops);
	if (!cache)
		return NULL;

	if (handle && nl_cache_refill(handle, cache) < 0) {
		free(cache);
		return NULL;
	}

	return cache;
}

/** @} */

/**
 * @name Route Addition
 * @{
 */

static struct nl_msg *build_route_msg(struct rtnl_route *tmpl, int cmd,
				      int flags)
{
	struct nl_msg *msg;
	struct nl_addr *addr;
	int scope, i, oif, nmetrics = 0;
	struct nlattr *metrics;
	struct rtmsg rtmsg = {
		.rtm_family = rtnl_route_get_family(tmpl),
		.rtm_dst_len = rtnl_route_get_dst_len(tmpl),
		.rtm_src_len = rtnl_route_get_src_len(tmpl),
		.rtm_tos = rtnl_route_get_tos(tmpl),
		.rtm_table = rtnl_route_get_table(tmpl),
		.rtm_type = rtnl_route_get_type(tmpl),
		.rtm_protocol = rtnl_route_get_protocol(tmpl),
		.rtm_flags = rtnl_route_get_flags(tmpl),
	};

	if (rtmsg.rtm_family == AF_UNSPEC) {
		nl_error(EINVAL, "Cannot build route message, address " \
				 "family is unknown.");
		return NULL;
	}

	scope = rtnl_route_get_scope(tmpl);
	if (scope == RT_SCOPE_NOWHERE) {
		if (rtmsg.rtm_type == RTN_LOCAL)
			scope = RT_SCOPE_HOST;
		else {
			/* XXX Change to UNIVERSE if gw || nexthops */
			scope = RT_SCOPE_LINK;
		}
	}

	rtmsg.rtm_scope = scope;

	msg = nlmsg_alloc_simple(cmd, flags);
	if (msg == NULL)
		return NULL;

	if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), NLMSG_ALIGNTO) < 0)
		goto nla_put_failure;

	addr = rtnl_route_get_dst(tmpl);
	if (addr)
		NLA_PUT_ADDR(msg, RTA_DST, addr);

	addr = rtnl_route_get_src(tmpl);
	if (addr)
		NLA_PUT_ADDR(msg, RTA_SRC, addr);

	addr = rtnl_route_get_gateway(tmpl);
	if (addr)
		NLA_PUT_ADDR(msg, RTA_GATEWAY, addr);

	addr = rtnl_route_get_pref_src(tmpl);
	if (addr)
		NLA_PUT_ADDR(msg, RTA_PREFSRC, addr);

	NLA_PUT_U32(msg, RTA_PRIORITY, rtnl_route_get_prio(tmpl));

	oif = rtnl_route_get_oif(tmpl);
	if (oif != RTNL_LINK_NOT_FOUND)
		NLA_PUT_U32(msg, RTA_OIF, oif);

	for (i = 1; i <= RTAX_MAX; i++)
		if (rtnl_route_get_metric(tmpl, i) != UINT_MAX)
			nmetrics++;

	if (nmetrics > 0) {
		unsigned int val;

		metrics = nla_nest_start(msg, RTA_METRICS);
		if (metrics == NULL)
			goto nla_put_failure;

		for (i = 1; i <= RTAX_MAX; i++) {
			val = rtnl_route_get_metric(tmpl, i);
			if (val != UINT_MAX)
				NLA_PUT_U32(msg, i, val);
		}

		nla_nest_end(msg, metrics);
	}

#if 0
	RTA_IIF,
	RTA_MULTIPATH,
	RTA_PROTOINFO,
	RTA_FLOW,
	RTA_CACHEINFO,
	RTA_SESSION,
	RTA_MP_ALGO,
#endif

	return msg;

nla_put_failure:
	nlmsg_free(msg);
	return NULL;
}

struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags)
{
	return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags);
}

int rtnl_route_add(struct nl_handle *handle, struct rtnl_route *route,
		   int flags)
{
	struct nl_msg *msg;
	int err;

	msg = rtnl_route_build_add_request(route, flags);
	if (!msg)
		return nl_get_errno();

	err = nl_send_auto_complete(handle, msg);
	nlmsg_free(msg);
	if (err < 0)
		return err;

	return nl_wait_for_ack(handle);
}

struct nl_msg *rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags)
{
	return build_route_msg(tmpl, RTM_DELROUTE, flags);
}

int rtnl_route_del(struct nl_handle *handle, struct rtnl_route *route,
		   int flags)
{
	struct nl_msg *msg;
	int err;

	msg = rtnl_route_build_del_request(route, flags);
	if (!msg)
		return nl_get_errno();

	err = nl_send_auto_complete(handle, msg);
	nlmsg_free(msg);
	if (err < 0)
		return err;

	return nl_wait_for_ack(handle);
}

/** @} */

static struct nl_af_group route_groups[] = {
	{ AF_INET,	RTNLGRP_IPV4_ROUTE },
	{ AF_INET6,	RTNLGRP_IPV6_ROUTE },
	{ AF_DECnet,	RTNLGRP_DECnet_ROUTE },
	{ END_OF_GROUP_LIST },
};

static struct nl_cache_ops rtnl_route_ops = {
	.co_name		= "route/route",
	.co_hdrsize		= sizeof(struct rtmsg),
	.co_msgtypes		= {
					{ RTM_NEWROUTE, NL_ACT_NEW, "new" },
					{ RTM_DELROUTE, NL_ACT_DEL, "del" },
					{ RTM_GETROUTE, NL_ACT_GET, "get" },
					END_OF_MSGTYPES_LIST,
				  },
	.co_protocol		= NETLINK_ROUTE,
	.co_groups		= route_groups,
	.co_request_update	= route_request_update,
	.co_msg_parser		= route_msg_parser,
	.co_obj_ops		= &route_obj_ops,
};

static void __init route_init(void)
{
	nl_cache_mngt_register(&rtnl_route_ops);
}

static void __exit route_exit(void)
{
	nl_cache_mngt_unregister(&rtnl_route_ops);
}
예제 #17
0
파일: libipvs.c 프로젝트: Am1GO/keepalived
static int ipvs_services_parse_cb(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
	struct nlattr *svc_attrs[IPVS_SVC_ATTR_MAX + 1];
	struct ip_vs_get_services **getp = (struct ip_vs_get_services **)arg;
	struct ip_vs_get_services *get = (struct ip_vs_get_services *)*getp;
	struct ip_vs_flags flags;
	int i = get->num_services;

	if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
		return -1;

	if (!attrs[IPVS_CMD_ATTR_SERVICE])
		return -1;

	if (nla_parse_nested(svc_attrs, IPVS_SVC_ATTR_MAX, attrs[IPVS_CMD_ATTR_SERVICE], ipvs_service_policy))
		return -1;

	memset(&(get->entrytable[i]), 0, sizeof(get->entrytable[i]));

	if (!(svc_attrs[IPVS_SVC_ATTR_AF] &&
	      (svc_attrs[IPVS_SVC_ATTR_FWMARK] ||
	       (svc_attrs[IPVS_SVC_ATTR_PROTOCOL] &&
		svc_attrs[IPVS_SVC_ATTR_ADDR] &&
		svc_attrs[IPVS_SVC_ATTR_PORT])) &&
	      svc_attrs[IPVS_SVC_ATTR_SCHED_NAME] &&
	      svc_attrs[IPVS_SVC_ATTR_NETMASK] &&
	      svc_attrs[IPVS_SVC_ATTR_TIMEOUT] &&
	      svc_attrs[IPVS_SVC_ATTR_FLAGS]))
		return -1;

	get->entrytable[i].af = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_AF]);

	if (svc_attrs[IPVS_SVC_ATTR_FWMARK])
		get->entrytable[i].fwmark = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_FWMARK]);
	else {
		get->entrytable[i].protocol = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_PROTOCOL]);
		memcpy(&(get->entrytable[i].addr), nla_data(svc_attrs[IPVS_SVC_ATTR_ADDR]),
		       sizeof(get->entrytable[i].addr));
		get->entrytable[i].port = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_PORT]);
	}

	strncpy(get->entrytable[i].sched_name,
		nla_get_string(svc_attrs[IPVS_SVC_ATTR_SCHED_NAME]),
		IP_VS_SCHEDNAME_MAXLEN);

	if (svc_attrs[IPVS_SVC_ATTR_PE_NAME])
		strncpy(get->entrytable[i].pe_name,
			nla_get_string(svc_attrs[IPVS_SVC_ATTR_PE_NAME]),
			IP_VS_PENAME_MAXLEN);

	get->entrytable[i].netmask = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_NETMASK]);
	get->entrytable[i].timeout = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_TIMEOUT]);
	nla_memcpy(&flags, svc_attrs[IPVS_SVC_ATTR_FLAGS], sizeof(flags));
	get->entrytable[i].flags = flags.flags & flags.mask;

	if (ipvs_parse_stats(&(get->entrytable[i].stats),
			     svc_attrs[IPVS_SVC_ATTR_STATS]) != 0)
		return -1;

	get->entrytable[i].num_dests = 0;

	i++;

	get->num_services = i;
	get = realloc(get, sizeof(*get)
	      + sizeof(ipvs_service_entry_t) * (get->num_services + 1));
	*getp = get;
	return 0;
}
예제 #18
0
static int nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
	struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
	struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
	struct nlattr *nl_band, *nl_freq;
	int rem_band, rem_freq, num_freq = 0;
	uint32_t freq;
	struct nl80211_channel_block *chanb = (struct nl80211_channel_block *) arg;

	nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
			  genlmsg_attrlen(gnlh, 0), NULL);

	if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) {
		return NL_SKIP;
	}

	if (tb_msg[NL80211_ATTR_WIPHY_NAME]) {
		if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]), 
				   chanb->phyname) != 0) {
			return NL_SKIP;
		}
	}

	// Count the number of channels
	for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]),
		 rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]);
		 nla_ok(nl_band, rem_band); 
		 nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) {

		nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band),
				  nla_len(nl_band), NULL);

		for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]),
			 rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]);
			 nla_ok(nl_freq, rem_freq); 
			 nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) {

			nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, 
					  (struct nlattr *) nla_data(nl_freq),
					  nla_len(nl_freq), NULL);

			if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
				continue;

			if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
				continue;

			num_freq++;
		}
	}

	chanb->nfreqs = num_freq;
	chanb->channel_list = malloc(sizeof(int) * num_freq);
	num_freq = 0;

	// Assemble a return
	for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]),
		 rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]);
		 nla_ok(nl_band, rem_band); 
		 nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) {

		nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band),
				  nla_len(nl_band), NULL);

		for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]),
			 rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]);
			 nla_ok(nl_freq, rem_freq); 
			 nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) {

			nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, 
					  (struct nlattr *) nla_data(nl_freq),
					  nla_len(nl_freq), NULL);

			if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
				continue;

			if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
				continue;

			freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);

			chanb->channel_list[num_freq++] = FreqToChan(freq);
		}
	}

	return NL_SKIP;
}
예제 #19
0
static int netlink_msg_handler(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *hdr;
	struct tcmsg *tcm;
	struct nlattr *attrs[TCA_MAX+1];
	struct nlattr *stat_attrs[TCA_STATS_MAX+1];
	struct qdisc_handler *h;
	char qdisc[IFNAMSIZ] = {0};
	int qdisc_l = 0;
	char ifname[IFNAMSIZ] = {0};
	int ifname_l = 0;
	struct timeval current_time = {0};
	double time;

	char *ret = NULL;

	struct gnet_stats_basic *sb;
	struct gnet_stats_queue *q;

	struct options *opt = arg;

	struct recordset rset = {0};

	hdr = nlmsg_hdr(msg);
	tcm = nlmsg_data(hdr);
	if(!has_iface(opt, tcm->tcm_ifindex))
		return NL_SKIP;

	if((ret = rtnl_link_i2name(opt->cache, tcm->tcm_ifindex, ifname, IFNAMSIZ)) == NULL)
		return NL_SKIP;

	// No length checking in netlink library.
	if((ifname_l = 1 + strnlen(ifname, IFNAMSIZ)) >= IFNAMSIZ) {
		ifname[IFNAMSIZ-1] = '\0';
		ifname_l = IFNAMSIZ;
	}

	gettimeofday(&current_time, NULL);
	time = (double)current_time.tv_usec / 1000000 + (double) current_time.tv_sec;
	add_record_double(&rset, "time", sizeof("time"), time);
	add_record_str(&rset, "iface", sizeof("iface"), ifname, ifname_l);

	nlmsg_parse(hdr, sizeof(*tcm), attrs, TCA_MAX, tca_policy);

	if(attrs[TCA_KIND]) {
		qdisc_l = nla_len(attrs[TCA_KIND]);
		memcpy(qdisc, nla_get_string(attrs[TCA_KIND]), qdisc_l);
		add_record_str(&rset, "qdisc", sizeof("qdisc"), qdisc, qdisc_l);
	}

	add_record_hex(&rset, "handle", sizeof("handle"), tcm->tcm_handle >> 16);

	if(attrs[TCA_STATS2]) {
		nla_parse_nested(stat_attrs, TCA_STATS_MAX, attrs[TCA_STATS2], tca_stats_policy);
		if(stat_attrs[TCA_STATS_BASIC]) {
			sb = nla_data(stat_attrs[TCA_STATS_BASIC]);
			add_record_uint(&rset, "bytes", sizeof("bytes"), sb->bytes);
			add_record_uint(&rset, "packets", sizeof("packets"), sb->packets);
		}

		if(stat_attrs[TCA_STATS_QUEUE]) {
			q = nla_data(stat_attrs[TCA_STATS_QUEUE]);
			add_record_uint(&rset, "drops", sizeof("drops"), q->drops);
			add_record_uint(&rset, "qlen", sizeof("qlen"), q->qlen);
			add_record_uint(&rset, "backlog", sizeof("backlog"), q->backlog);
			add_record_uint(&rset, "overlimits", sizeof("overlimits"), q->overlimits);
			add_record_uint(&rset, "requeues", sizeof("requeues"), q->requeues);
		}
		if(stat_attrs[TCA_STATS_APP]) {
			h = find_qdisc_handler(qdisc);
			if(h)
				h->parse_stats(stat_attrs[TCA_STATS_APP], &rset);
		}
	}
	opt->formatter->format(opt->formatter, &rset);
	clear_records(&rset);
	if(!opt->run_length || current_time.tv_sec < opt->start_time.tv_sec + opt->run_length)
		return NL_OK;
	else
		return NL_STOP;
}