예제 #1
0
static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid,
	u32 seq, int flags, struct net_device *dev)
{
	void *hdr;
	struct wpan_phy *phy;

	pr_debug("%s\n", __func__);

	hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
		IEEE802154_LIST_IFACE);
	if (!hdr)
		goto out;

	phy = ieee802154_mlme_ops(dev)->get_phy(dev);
	BUG_ON(!phy);

	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
	NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));
	NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex);

	NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
		dev->dev_addr);
	NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR,
		ieee802154_mlme_ops(dev)->get_short_addr(dev));
	NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID,
		ieee802154_mlme_ops(dev)->get_pan_id(dev));
	wpan_phy_put(phy);
	return genlmsg_end(msg, hdr);

nla_put_failure:
	wpan_phy_put(phy);
	genlmsg_cancel(msg, hdr);
out:
	return -EMSGSIZE;
}
예제 #2
0
static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
				struct l2tp_session *session)
{
	void *hdr;
	struct nlattr *nest;
	struct l2tp_tunnel *tunnel = session->tunnel;
	struct sock *sk = NULL;

	sk = tunnel->sock;

	hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET);
	if (IS_ERR(hdr))
		return PTR_ERR(hdr);

	NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id);
	NLA_PUT_U32(skb, L2TP_ATTR_SESSION_ID, session->session_id);
	NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id);
	NLA_PUT_U32(skb, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id);
	NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, session->debug);
	NLA_PUT_U16(skb, L2TP_ATTR_PW_TYPE, session->pwtype);
	NLA_PUT_U16(skb, L2TP_ATTR_MTU, session->mtu);
	if (session->mru)
		NLA_PUT_U16(skb, L2TP_ATTR_MRU, session->mru);

	if (session->ifname && session->ifname[0])
		NLA_PUT_STRING(skb, L2TP_ATTR_IFNAME, session->ifname);
	if (session->cookie_len)
		NLA_PUT(skb, L2TP_ATTR_COOKIE, session->cookie_len, &session->cookie[0]);
	if (session->peer_cookie_len)
		NLA_PUT(skb, L2TP_ATTR_PEER_COOKIE, session->peer_cookie_len, &session->peer_cookie[0]);
	NLA_PUT_U8(skb, L2TP_ATTR_RECV_SEQ, session->recv_seq);
	NLA_PUT_U8(skb, L2TP_ATTR_SEND_SEQ, session->send_seq);
	NLA_PUT_U8(skb, L2TP_ATTR_LNS_MODE, session->lns_mode);
#ifdef CONFIG_XFRM
	if ((sk) && (sk->sk_policy[0] || sk->sk_policy[1]))
		NLA_PUT_U8(skb, L2TP_ATTR_USING_IPSEC, 1);
#endif
	if (session->reorder_timeout)
		NLA_PUT_MSECS(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout);

	nest = nla_nest_start(skb, L2TP_ATTR_STATS);
	if (nest == NULL)
		goto nla_put_failure;
	NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, session->stats.tx_packets);
	NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, session->stats.tx_bytes);
	NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, session->stats.tx_errors);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, session->stats.rx_packets);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, session->stats.rx_bytes);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, session->stats.rx_seq_discards);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, session->stats.rx_oos_packets);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, session->stats.rx_errors);
	nla_nest_end(skb, nest);

	return genlmsg_end(skb, hdr);

 nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}
예제 #3
0
static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
			       struct l2tp_tunnel *tunnel)
{
	void *hdr;
	struct nlattr *nest;
	struct sock *sk = NULL;
	struct inet_sock *inet;

	hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags,
			  L2TP_CMD_TUNNEL_GET);
	if (IS_ERR(hdr))
		return PTR_ERR(hdr);

	NLA_PUT_U8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version);
	NLA_PUT_U32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id);
	NLA_PUT_U32(skb, L2TP_ATTR_PEER_CONN_ID, tunnel->peer_tunnel_id);
	NLA_PUT_U32(skb, L2TP_ATTR_DEBUG, tunnel->debug);
	NLA_PUT_U16(skb, L2TP_ATTR_ENCAP_TYPE, tunnel->encap);

	nest = nla_nest_start(skb, L2TP_ATTR_STATS);
	if (nest == NULL)
		goto nla_put_failure;

	NLA_PUT_U64(skb, L2TP_ATTR_TX_PACKETS, tunnel->stats.tx_packets);
	NLA_PUT_U64(skb, L2TP_ATTR_TX_BYTES, tunnel->stats.tx_bytes);
	NLA_PUT_U64(skb, L2TP_ATTR_TX_ERRORS, tunnel->stats.tx_errors);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_PACKETS, tunnel->stats.rx_packets);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_BYTES, tunnel->stats.rx_bytes);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, tunnel->stats.rx_seq_discards);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_OOS_PACKETS, tunnel->stats.rx_oos_packets);
	NLA_PUT_U64(skb, L2TP_ATTR_RX_ERRORS, tunnel->stats.rx_errors);
	nla_nest_end(skb, nest);

	sk = tunnel->sock;
	if (!sk)
		goto out;

	inet = inet_sk(sk);

	switch (tunnel->encap) {
	case L2TP_ENCAPTYPE_UDP:
		NLA_PUT_U16(skb, L2TP_ATTR_UDP_SPORT, ntohs(inet->inet_sport));
		NLA_PUT_U16(skb, L2TP_ATTR_UDP_DPORT, ntohs(inet->inet_dport));
		NLA_PUT_U8(skb, L2TP_ATTR_UDP_CSUM, (sk->sk_no_check != UDP_CSUM_NOXMIT));
		/* NOBREAK */
	case L2TP_ENCAPTYPE_IP:
		NLA_PUT_BE32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr);
		NLA_PUT_BE32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr);
		break;
	}

out:
	return genlmsg_end(skb, hdr);

nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}
예제 #4
0
파일: libipvs.c 프로젝트: Am1GO/keepalived
static int ipvs_nl_fill_service_attr(struct nl_msg *msg, ipvs_service_t *svc)
{
	struct nlattr *nl_service;
	struct ip_vs_flags flags = { .flags = svc->flags,
				     .mask = ~0 };

	nl_service = nla_nest_start(msg, IPVS_CMD_ATTR_SERVICE);
	if (!nl_service)
		return -1;

	NLA_PUT_U16(msg, IPVS_SVC_ATTR_AF, svc->af);

	if (svc->fwmark) {
		NLA_PUT_U32(msg, IPVS_SVC_ATTR_FWMARK, svc->fwmark);
	} else {
		NLA_PUT_U16(msg, IPVS_SVC_ATTR_PROTOCOL, svc->protocol);
		NLA_PUT(msg, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &(svc->addr));
		NLA_PUT_U16(msg, IPVS_SVC_ATTR_PORT, svc->port);
	}

	NLA_PUT_STRING(msg, IPVS_SVC_ATTR_SCHED_NAME, svc->sched_name);
	if (svc->pe_name[0])
		NLA_PUT_STRING(msg, IPVS_SVC_ATTR_PE_NAME, svc->pe_name);
	NLA_PUT(msg, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags);
	NLA_PUT_U32(msg, IPVS_SVC_ATTR_TIMEOUT, svc->timeout);
	NLA_PUT_U32(msg, IPVS_SVC_ATTR_NETMASK, svc->netmask);

	nla_nest_end(msg, nl_service);
	return 0;

nla_put_failure:
	return -1;
}
#endif

int ipvs_add_service(ipvs_service_t *svc)
{
	ipvs_func = ipvs_add_service;
#ifdef LIBIPVS_USE_NL
	if (try_nl) {
		struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_NEW_SERVICE, 0);
		if (!msg) return -1;
		if (ipvs_nl_fill_service_attr(msg, svc)) {
			nlmsg_free(msg);
			return -1;
		}
		return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);
	}
#endif

	CHECK_COMPAT_SVC(svc, -1);
	return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_ADD, (char *)svc,
			  sizeof(struct ip_vs_service_kern));
out_err:
	return -1;
}
예제 #5
0
파일: libipvs.c 프로젝트: Crazykev/ipvsadm
int ipvs_start_daemon(ipvs_daemon_t *dm)
{
	struct ip_vs_daemon_kern dmk;

	ipvs_func = ipvs_start_daemon;
#ifdef LIBIPVS_USE_NL
	if (try_nl) {
		struct nlattr *nl_daemon;
		struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_NEW_DAEMON, 0);
		if (!msg) return -1;

		nl_daemon = nla_nest_start(msg, IPVS_CMD_ATTR_DAEMON);
		if (!nl_daemon)
			goto nla_put_failure;

		NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_STATE, dm->state);
		NLA_PUT_STRING(msg, IPVS_DAEMON_ATTR_MCAST_IFN, dm->mcast_ifn);
		NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_SYNC_ID, dm->syncid);
		if (dm->sync_maxlen)
			NLA_PUT_U16(msg, IPVS_DAEMON_ATTR_SYNC_MAXLEN,
				    dm->sync_maxlen);
		if (dm->mcast_port)
			NLA_PUT_U16(msg, IPVS_DAEMON_ATTR_MCAST_PORT,
				    dm->mcast_port);
		if (dm->mcast_ttl)
			NLA_PUT_U8(msg, IPVS_DAEMON_ATTR_MCAST_TTL,
				   dm->mcast_ttl);
		if (AF_INET6 == dm->mcast_af)
			NLA_PUT(msg, IPVS_DAEMON_ATTR_MCAST_GROUP6,
				sizeof(dm->mcast_group.in6),
				&dm->mcast_group.in6);
		else if (AF_INET == dm->mcast_af)
			NLA_PUT_U32(msg, IPVS_DAEMON_ATTR_MCAST_GROUP,
				    dm->mcast_group.ip);

		nla_nest_end(msg, nl_daemon);

		return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL);

nla_put_failure:
		nlmsg_free(msg);
		return -1;
	}
#endif
	memset(&dmk, 0, sizeof(dmk));
	dmk.state = dm->state;
	strcpy(dmk.mcast_ifn, dm->mcast_ifn);
	dmk.syncid = dm->syncid;
	return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_STARTDAEMON,
			  (char *)&dmk, sizeof(dmk));
}
예제 #6
0
static iz_res_t set_request(struct iz_cmd *cmd, struct nl_msg *msg)
{
	char *dummy;
	uint16_t pan_id, short_addr;
	uint8_t chan;

	if (!cmd->argv[1])
		return IZ_STOP_ERR;
	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, cmd->argv[1]);

	if (!cmd->argv[2])
		return IZ_STOP_ERR;
	pan_id = strtol(cmd->argv[2], &dummy, 16);
	if (*dummy) {
		printf("Bad PAN ID!\n");
		return IZ_STOP_ERR;
	}
	NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, pan_id);

	if (!cmd->argv[3])
		return IZ_STOP_ERR;
	short_addr = strtol(cmd->argv[3], &dummy, 16);
	if (*dummy) {
		printf("Bad short address!\n");
		return IZ_STOP_ERR;
	}
	NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, short_addr);

	if (!cmd->argv[4])
		return IZ_STOP_ERR;
	chan = strtol(cmd->argv[4], &dummy, 10);
	if (*dummy) {
		printf("Bad channel number!\n");
		return IZ_STOP_ERR;
	}
	NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, chan);

	/* set all unneeded attributes to 0*/
	NLA_PUT_U8(msg, IEEE802154_ATTR_PAN_COORD, 0);
	NLA_PUT_U8(msg, IEEE802154_ATTR_BCN_ORD, 0);
	NLA_PUT_U8(msg, IEEE802154_ATTR_SF_ORD, 0);
	NLA_PUT_U8(msg, IEEE802154_ATTR_BAT_EXT, 0);
	NLA_PUT_U8(msg, IEEE802154_ATTR_COORD_REALIGN, 0);

	return IZ_CONT_OK;

nla_put_failure:
	return IZ_STOP_ERR;
}
예제 #7
0
int ieee802154_nl_disassoc_indic(struct net_device *dev,
		struct ieee802154_addr *addr, u8 reason)
{
	struct sk_buff *msg;

	pr_debug("%s\n", __func__);

	msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC);
	if (!msg)
		return -ENOBUFS;

	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
	NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex);
	NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
			dev->dev_addr);

	if (addr->addr_type == IEEE802154_ADDR_LONG)
		NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN,
				addr->hwaddr);
	else
		NLA_PUT_U16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
				addr->short_addr);

	NLA_PUT_U8(msg, IEEE802154_ATTR_REASON, reason);

	return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);

nla_put_failure:
	nlmsg_free(msg);
	return -ENOBUFS;
}
예제 #8
0
파일: mgmt.c 프로젝트: greearb/iw-ct
static int register_mgmt_frame(struct nl80211_state *state,
			       struct nl_msg *msg, int argc, char **argv,
			       enum id_input id)
{
	unsigned int type;
	unsigned char *match;
	size_t match_len;
	int ret;

	ret = sscanf(argv[0], "%x", &type);
	if (ret != 1) {
		printf("invalid frame type: %s\n", argv[0]);
		return 2;
	}

	match = parse_hex(argv[1], &match_len);
	if (!match) {
		printf("invalid frame pattern: %s\n", argv[1]);
		return 2;
	}

	NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
	NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);

	return 0;

nla_put_failure:
	return -ENOBUFS;
}
예제 #9
0
int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr,
		u8 status)
{
	struct sk_buff *msg;

	pr_debug("%s\n", __func__);

	msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF);
	if (!msg)
		return -ENOBUFS;

	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
	NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex);
	NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
			dev->dev_addr);

	NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr);
	NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status);

	return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);

nla_put_failure:
	nlmsg_free(msg);
	return -ENOBUFS;
}
예제 #10
0
static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
				struct netlink_callback *cb, int flags)
{
	void *hdr;

	hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
			  &nfc_genl_family, flags, NFC_CMD_GET_TARGET);
	if (!hdr)
		return -EMSGSIZE;

	genl_dump_check_consistent(cb, hdr, &nfc_genl_family);

	NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);
	NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, target->supported_protocols);
	NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);
	NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);
	if (target->nfcid1_len > 0)
		NLA_PUT(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len,
			target->nfcid1);
	if (target->sensb_res_len > 0)
		NLA_PUT(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len,
			target->sensb_res);
	if (target->sensf_res_len > 0)
		NLA_PUT(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len,
			target->sensf_res);

	return genlmsg_end(msg, hdr);

nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}
예제 #11
0
파일: exp.c 프로젝트: arend/libnl
static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags,
				 struct nl_msg **result)
{
	struct nl_msg *msg;
	int err;

	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK_EXP, cmd, flags,
				   nfnl_exp_get_family(exp), 0);
	if (msg == NULL)
		return -NLE_NOMEM;

	if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0)
		goto err_out;

	if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0)
		goto err_out;

	if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0)
		goto err_out;

	if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) {
		if ((err = nfnl_exp_build_nat(msg, exp)) < 0)
			goto err_out;
	}

	if (nfnl_exp_test_class(exp))
		NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp)));

	if (nfnl_exp_test_fn(exp))
		NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp));

	if (nfnl_exp_test_id(exp))
		NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp)));

	if (nfnl_exp_test_timeout(exp))
		NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp)));

	if (nfnl_exp_test_helper_name(exp))
		NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp));

	if (nfnl_exp_test_zone(exp))
		NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp)));

	if (nfnl_exp_test_flags(exp))
		NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp)));

	*result = msg;
	return 0;

nla_put_failure:
err_out:
	nlmsg_free(msg);
	return err;
}
예제 #12
0
파일: libipvs.c 프로젝트: Crazykev/ipvsadm
static int ipvs_nl_fill_dest_attr(struct nl_msg *msg, ipvs_dest_t *dst)
{
	struct nlattr *nl_dest;

	nl_dest = nla_nest_start(msg, IPVS_CMD_ATTR_DEST);
	if (!nl_dest)
		return -1;

	NLA_PUT_U16(msg, IPVS_DEST_ATTR_ADDR_FAMILY, dst->af);
	NLA_PUT(msg, IPVS_DEST_ATTR_ADDR, sizeof(dst->addr), &(dst->addr));
	NLA_PUT_U16(msg, IPVS_DEST_ATTR_PORT, dst->port);
	NLA_PUT_U32(msg, IPVS_DEST_ATTR_FWD_METHOD, dst->conn_flags & IP_VS_CONN_F_FWD_MASK);
	NLA_PUT_U32(msg, IPVS_DEST_ATTR_WEIGHT, dst->weight);
	NLA_PUT_U32(msg, IPVS_DEST_ATTR_U_THRESH, dst->u_threshold);
	NLA_PUT_U32(msg, IPVS_DEST_ATTR_L_THRESH, dst->l_threshold);

	nla_nest_end(msg, nl_dest);
	return 0;

nla_put_failure:
	return -1;
}
예제 #13
0
static iz_res_t disassoc_request(struct iz_cmd *cmd, struct nl_msg *msg)
{
	char *dummy;
	uint8_t reason;
	unsigned char hwa[IEEE802154_ADDR_LEN];
	uint16_t  short_addr;
	int ret;

	if (!cmd->argv[1])
		return IZ_STOP_ERR;
	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, cmd->argv[1]);

	if (!cmd->argv[2])
		return IZ_STOP_ERR;
	if (cmd->argv[2][0] == 'H' || cmd->argv[2][0] == 'h') {
		ret = parse_hw_addr(cmd->argv[2]+1, hwa);
		if (ret) {
			printf("Bad destination address!\n");
			return IZ_STOP_ERR;
		}
		NLA_PUT(msg, IEEE802154_ATTR_DEST_HW_ADDR,
			IEEE802154_ADDR_LEN, hwa);
	} else {
		short_addr = strtol(cmd->argv[2], &dummy, 16);
		if (*dummy) {
			printf("Bad destination address!\n");
			return IZ_STOP_ERR;
		}
		NLA_PUT_U16(msg, IEEE802154_ATTR_DEST_SHORT_ADDR, short_addr);
	}

	if (!cmd->argv[3])
		return IZ_STOP_ERR;
	reason = strtol(cmd->argv[3], &dummy, 16);
	if (*dummy) {
		printf("Bad disassociation reason!\n");
		return IZ_STOP_ERR;
	}

	if (cmd->argv[4])
		return IZ_STOP_ERR;

	NLA_PUT_U8(msg, IEEE802154_ATTR_REASON, reason);

	return IZ_CONT_OK;

nla_put_failure:
	return IZ_STOP_ERR;

}
예제 #14
0
int ieee802154_nl_beacon_indic(struct net_device *dev,
		u16 panid, u16 coord_addr)
{
	struct sk_buff *msg;

	pr_debug("%s\n", __func__);

	msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC);
	if (!msg)
		return -ENOBUFS;

	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name);
	NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex);
	NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
			dev->dev_addr);
	NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr);
	NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid);

	return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);

nla_put_failure:
	nlmsg_free(msg);
	return -ENOBUFS;
}
예제 #15
0
파일: ct.c 프로젝트: Domikk/libnl
static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
				 struct nl_msg **result)
{
	struct nl_msg *msg;
	int err;

	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
				   nfnl_ct_get_family(ct), 0);
	if (msg == NULL)
		return -NLE_NOMEM;

	if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
		goto err_out;

	/* REPLY tuple is optional, dont add unless at least src/dst specified */

	if ( nfnl_ct_get_src(ct, 1) && nfnl_ct_get_dst(ct, 1) )
		if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0)
			goto err_out;

	if (nfnl_ct_test_status(ct))
		NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct)));

	if (nfnl_ct_test_timeout(ct))
		NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct)));

	if (nfnl_ct_test_mark(ct))
		NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct)));

	if (nfnl_ct_test_id(ct))
		NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct)));

	if (nfnl_ct_test_zone(ct))
		NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct)));

	*result = msg;
	return 0;

nla_put_failure:
err_out:
	nlmsg_free(msg);
	return err;
}
static int handle_interface_noack_map(struct nl80211_state *state,
				      struct nl_cb *cb,
				      struct nl_msg *msg,
				      int argc, char **argv,
				      enum id_input id)
{
	uint16_t noack_map;
	char *end;

	if (argc != 1)
		return 1;

	noack_map = strtoul(argv[0], &end, 16);
	if (*end)
		return 1;

	NLA_PUT_U16(msg, NL80211_ATTR_NOACK_MAP, noack_map);

	return 0;
 nla_put_failure:
	return -ENOBUFS;

}
예제 #17
0
파일: ct.c 프로젝트: DedulyaOtmoroz/libnl
static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
			       int repl)
{
	struct nlattr *tuple, *ip, *proto;
	struct nl_addr *addr;
	int family;

	family = nfnl_ct_get_family(ct);

	tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
	if (!tuple)
		goto nla_put_failure;

	ip = nla_nest_start(msg, CTA_TUPLE_IP);
	if (!ip)
		goto nla_put_failure;

	addr = nfnl_ct_get_src(ct, repl);
	if (addr)
		NLA_PUT_ADDR(msg,
			     family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
			     addr);

	addr = nfnl_ct_get_dst(ct, repl);
	if (addr)
		NLA_PUT_ADDR(msg,
			     family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
			     addr);

	nla_nest_end(msg, ip);

	proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
	if (!proto)
		goto nla_put_failure;

	if (nfnl_ct_test_proto(ct))
		NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));

	if (nfnl_ct_test_src_port(ct, repl))
		NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
			htons(nfnl_ct_get_src_port(ct, repl)));

	if (nfnl_ct_test_dst_port(ct, repl))
		NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
			htons(nfnl_ct_get_dst_port(ct, repl)));

	if (family == AF_INET) {
		if (nfnl_ct_test_icmp_id(ct, repl))
			NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
						htons(nfnl_ct_get_icmp_id(ct, repl)));

		if (nfnl_ct_test_icmp_type(ct, repl))
			NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
					   nfnl_ct_get_icmp_type(ct, repl));

		if (nfnl_ct_test_icmp_code(ct, repl))
			NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
					   nfnl_ct_get_icmp_code(ct, repl));
	} else if (family == AF_INET6) {
		if (nfnl_ct_test_icmp_id(ct, repl))
			NLA_PUT_U16(msg, CTA_PROTO_ICMPV6_ID,
						htons(nfnl_ct_get_icmp_id(ct, repl)));

		if (nfnl_ct_test_icmp_type(ct, repl))
			NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_TYPE,
					   nfnl_ct_get_icmp_type(ct, repl));

		if (nfnl_ct_test_icmp_code(ct, repl))
			NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_CODE,
					   nfnl_ct_get_icmp_code(ct, repl));
	}

	nla_nest_end(msg, proto);

	nla_nest_end(msg, tuple);
	return 0;

nla_put_failure:
	return -NLE_MSGSIZE;
}
예제 #18
0
파일: exp.c 프로젝트: arend/libnl
static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp,
			       int cta)
{
	struct nlattr *tuple, *ip, *proto;
	struct nl_addr *addr;
	int family;

	family = nfnl_exp_get_family(exp);

	int type = exp_get_tuple_attr(cta);

	if (cta == CTA_EXPECT_NAT)
		tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE);
	else
		tuple = nla_nest_start(msg, cta);

	if (!tuple)
		goto nla_put_failure;

	ip = nla_nest_start(msg, CTA_TUPLE_IP);
	if (!ip)
		goto nla_put_failure;

	addr = nfnl_exp_get_src(exp, type);
	if (addr)
		NLA_PUT_ADDR(msg,
			     family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
			     addr);

	addr = nfnl_exp_get_dst(exp, type);
	if (addr)
		NLA_PUT_ADDR(msg,
			     family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
			     addr);

	nla_nest_end(msg, ip);

	proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
	if (!proto)
		goto nla_put_failure;

	if (nfnl_exp_test_l4protonum(exp, type))
		NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type));

	if (nfnl_exp_test_ports(exp, type)) {
		NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
			htons(nfnl_exp_get_src_port(exp, type)));

		NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
			htons(nfnl_exp_get_dst_port(exp, type)));
	}

	if (nfnl_exp_test_icmp(exp, type)) {
		NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
			htons(nfnl_exp_get_icmp_id(exp, type)));

		NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
			    nfnl_exp_get_icmp_type(exp, type));

		NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
			    nfnl_exp_get_icmp_code(exp, type));
	}

	nla_nest_end(msg, proto);

	nla_nest_end(msg, tuple);
	return 0;

nla_put_failure:
	return -NLE_MSGSIZE;
}
예제 #19
0
파일: wowlan.c 프로젝트: resfi/resfi
static int wowlan_parse_tcp_file(struct nl_msg *msg, const char *fn)
{
	char buf[16768];
	int err = 1;
	FILE *f = fopen(fn, "r");
	struct nlattr *tcp;

	if (!f)
		return 1;
	tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION);
	if (!tcp)
		goto nla_put_failure;

	while (!feof(f)) {
		char *eol;

		if (!fgets(buf, sizeof(buf), f))
			break;

		eol = strchr(buf + 5, '\r');
		if (eol)
			*eol = 0;
		eol = strchr(buf + 5, '\n');
		if (eol)
			*eol = 0;

		if (strncmp(buf, "source=", 7) == 0) {
			struct in_addr in_addr;
			char *addr = buf + 7;
			char *port = strchr(buf + 7, ':');

			if (port) {
				*port = 0;
				port++;
			}
			if (inet_aton(addr, &in_addr) == 0)
				goto close;
			NLA_PUT_U32(msg, NL80211_WOWLAN_TCP_SRC_IPV4,
				    in_addr.s_addr);
			if (port)
				NLA_PUT_U16(msg, NL80211_WOWLAN_TCP_SRC_PORT,
					    atoi(port));
		} else if (strncmp(buf, "dest=", 5) == 0) {
			struct in_addr in_addr;
			char *addr = buf + 5;
			char *port = strchr(buf + 5, ':');
			char *mac;
			unsigned char macbuf[6];

			if (!port)
				goto close;
			*port = 0;
			port++;
			mac = strchr(port, '@');
			if (!mac)
				goto close;
			*mac = 0;
			mac++;
			if (inet_aton(addr, &in_addr) == 0)
				goto close;
			NLA_PUT_U32(msg, NL80211_WOWLAN_TCP_DST_IPV4,
				    in_addr.s_addr);
			NLA_PUT_U16(msg, NL80211_WOWLAN_TCP_DST_PORT,
				    atoi(port));
			if (mac_addr_a2n(macbuf, mac))
				goto close;
			NLA_PUT(msg, NL80211_WOWLAN_TCP_DST_MAC,
				6, macbuf);
		} else if (strncmp(buf, "data=", 5) == 0) {
			size_t len;
			unsigned char *pkt = parse_hex(buf + 5, &len);

			if (!pkt)
				goto close;
			NLA_PUT(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, len, pkt);
			free(pkt);
		} else if (strncmp(buf, "data.interval=", 14) == 0) {
			NLA_PUT_U32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL,
				    atoi(buf + 14));
		} else if (strncmp(buf, "wake=", 5) == 0) {
			unsigned char *pat, *mask;
			size_t patlen;

			if (parse_hex_mask(buf + 5, &pat, &patlen, &mask))
				goto close;
			NLA_PUT(msg, NL80211_WOWLAN_TCP_WAKE_MASK,
				DIV_ROUND_UP(patlen, 8), mask);
			NLA_PUT(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD,
				patlen, pat);
			free(mask);
			free(pat);
		} else if (strncmp(buf, "data.seq=", 9) == 0) {
			struct nl80211_wowlan_tcp_data_seq seq = {};
			char *len, *offs, *start;

			len = buf + 9;
			offs = strchr(len, ',');
			if (!offs)
				goto close;
			*offs = 0;
			offs++;
			start = strchr(offs, ',');
			if (start) {
				*start = 0;
				start++;
				seq.start = atoi(start);
			}
			seq.len = atoi(len);
			seq.offset = atoi(offs);

			NLA_PUT(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ,
				sizeof(seq), &seq);
		} else if (strncmp(buf, "data.tok=", 9) == 0) {
			struct nl80211_wowlan_tcp_data_token *tok;
			size_t stream_len;
			char *len, *offs, *toks;
			unsigned char *stream;

			len = buf + 9;
			offs = strchr(len, ',');
			if (!offs)
				goto close;
			*offs = 0;
			offs++;
			toks = strchr(offs, ',');
			if (!toks)
				goto close;
			*toks = 0;
			toks++;

			stream = parse_hex(toks, &stream_len);
			if (!stream)
				goto close;
			tok = malloc(sizeof(*tok) + stream_len);
			if (!tok) {
				free(stream);
				err = -ENOMEM;
				goto close;
			}

			tok->len = atoi(len);
			tok->offset = atoi(offs);
			memcpy(tok->token_stream, stream, stream_len);

			NLA_PUT(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN,
				sizeof(*tok) + stream_len, tok);
			free(stream);
			free(tok);
		} else {
			if (buf[0] == '#')
				continue;
			goto close;
		}
	}

	err = 0;
	goto close;
 nla_put_failure:
	err = -ENOBUFS;
 close:
	fclose(f);
	nla_nest_end(msg, tcp);
	return err;
}
예제 #20
0
static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
{
	struct vlan_info *vi = link->l_info;
	struct nlattr *data;

	if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
		return -NLE_MSGSIZE;

	if (vi->vi_mask & VLAN_HAS_ID)
		NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id);

	if (vi->vi_mask & VLAN_HAS_FLAGS) {
		struct ifla_vlan_flags flags = {
			.flags = vi->vi_flags,
			.mask = vi->vi_flags_mask,
		};

		NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags);
	}

	if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) {
		struct ifla_vlan_qos_mapping map;
		struct nlattr *qos;
		int i;

		if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
			goto nla_put_failure;

		for (i = 0; i <= VLAN_PRIO_MAX; i++) {
			if (vi->vi_ingress_qos[i]) {
				map.from = i;
				map.to = vi->vi_ingress_qos[i];

				NLA_PUT(msg, i, sizeof(map), &map);
			}
		}

		nla_nest_end(msg, qos);
	}

	if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
		struct ifla_vlan_qos_mapping map;
		struct nlattr *qos;
		int i;

		if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
			goto nla_put_failure;

		for (i = 0; i < vi->vi_negress; i++) {
			map.from = vi->vi_egress_qos[i].vm_from;
			map.to = vi->vi_egress_qos[i].vm_to;

			NLA_PUT(msg, i, sizeof(map), &map);
		}

		nla_nest_end(msg, qos);
	}

	nla_nest_end(msg, data);

nla_put_failure:

	return 0;
}

static struct rtnl_link_info_ops vlan_info_ops = {
	.io_name		= "vlan",
	.io_alloc		= vlan_alloc,
	.io_parse		= vlan_parse,
	.io_dump = {
	    [NL_DUMP_LINE]	= vlan_dump_line,
	    [NL_DUMP_DETAILS]	= vlan_dump_details,
	},
	.io_clone		= vlan_clone,
예제 #21
0
파일: libipvs.c 프로젝트: Am1GO/keepalived
struct ip_vs_get_dests *ipvs_get_dests(ipvs_service_entry_t *svc)
{
	struct ip_vs_get_dests *d;
	struct ip_vs_get_dests_kern *dk;
	socklen_t len;
	int i;

	len = sizeof(*d) + sizeof(ipvs_dest_entry_t) * svc->num_dests;
	if (!(d = malloc(len)))
		return NULL;

	ipvs_func = ipvs_get_dests;

#ifdef LIBIPVS_USE_NL
	if (try_nl) {
		struct nl_msg *msg;
		struct nlattr *nl_service;
		if (svc->num_dests == 0)
			d = realloc(d,sizeof(*d) + sizeof(ipvs_dest_entry_t));
		d->fwmark = svc->fwmark;
		d->protocol = svc->protocol;
		d->addr = svc->addr;
		d->port = svc->port;
		d->num_dests = svc->num_dests;
		d->af = svc->af;

		msg = ipvs_nl_message(IPVS_CMD_GET_DEST, NLM_F_DUMP);
		if (!msg)
			goto ipvs_nl_dest_failure;

		nl_service = nla_nest_start(msg, IPVS_CMD_ATTR_SERVICE);
		if (!nl_service)
			goto nla_put_failure;

		NLA_PUT_U16(msg, IPVS_SVC_ATTR_AF, svc->af);

		if (svc->fwmark) {
			NLA_PUT_U32(msg, IPVS_SVC_ATTR_FWMARK, svc->fwmark);
		} else {
			NLA_PUT_U16(msg, IPVS_SVC_ATTR_PROTOCOL, svc->protocol);
			NLA_PUT(msg, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr),
				&svc->addr);
			NLA_PUT_U16(msg, IPVS_SVC_ATTR_PORT, svc->port);
		}

		nla_nest_end(msg, nl_service);
		if (ipvs_nl_send_message(msg, ipvs_dests_parse_cb, &d))
			goto ipvs_nl_dest_failure;

		return d;

nla_put_failure:
		nlmsg_free(msg);
ipvs_nl_dest_failure:
		free(d);
		return NULL;
	}
#endif

	if (svc->af != AF_INET) {
	  errno = EAFNOSUPPORT;
	  free(d);
	  return NULL;
	}

	len = sizeof(*dk) + sizeof(struct ip_vs_dest_entry_kern) * svc->num_dests;
	if (!(dk = malloc(len))) {
		free(d);
		return NULL;
	}

	dk->fwmark = svc->fwmark;
	dk->protocol = svc->protocol;
	dk->addr = svc->addr.ip;
	dk->port = svc->port;
	dk->num_dests = svc->num_dests;

	if (getsockopt(sockfd, IPPROTO_IP,
		       IP_VS_SO_GET_DESTS, dk, &len) < 0) {
		free(d);
		free(dk);
		return NULL;
	}
	memcpy(d, dk, sizeof(struct ip_vs_get_dests_kern));
	d->af = AF_INET;
	d->addr.ip = d->__addr_v4;
	for (i = 0; i < dk->num_dests; i++) {
		memcpy(&d->entrytable[i], &dk->entrytable[i],
		       sizeof(struct ip_vs_dest_entry_kern));
		d->entrytable[i].af = AF_INET;
		d->entrytable[i].addr.ip = d->entrytable[i].__addr_v4;
	}
	free(dk);
	return d;
}
예제 #22
0
static iz_res_t assoc_request(struct iz_cmd *cmd, struct nl_msg *msg)
{
	char *dummy;
	uint16_t pan_id, coord_short_addr;
	uint8_t chan;
	unsigned char hwa[IEEE802154_ADDR_LEN];
	int ret;
	uint8_t cap =  0
			| (1 << 1) /* FFD */
			| (1 << 3) /* Receiver ON */
			/*| (1 << 7) */ /* allocate short */
			;

	if (!cmd->argv[1])
		return IZ_STOP_ERR;
	NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, cmd->argv[1]);

	if (!cmd->argv[2])
		return IZ_STOP_ERR;
	pan_id = strtol(cmd->argv[2], &dummy, 16);
	if (*dummy) {
		printf("Bad PAN ID!\n");
		return IZ_STOP_ERR;
	}

	if (!cmd->argv[3])
		return IZ_STOP_ERR;
	if (cmd->argv[3][0] == 'H' || cmd->argv[3][0] == 'h') {
		ret = parse_hw_addr(cmd->argv[3]+1, hwa);
		if (ret) {
			printf("Bad coordinator address!\n");
			return IZ_STOP_ERR;
		}
		NLA_PUT(msg, IEEE802154_ATTR_COORD_HW_ADDR,
			IEEE802154_ADDR_LEN, hwa);
	} else {
		coord_short_addr = strtol(cmd->argv[3], &dummy, 16);
		if (*dummy) {
			printf("Bad coordinator address!\n");
			return IZ_STOP_ERR;
		}
		NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR,
			coord_short_addr);
	}


	if (!cmd->argv[4])
		return IZ_STOP_ERR;
	chan = strtol(cmd->argv[4], &dummy, 10);
	if (*dummy) {
		printf("Bad channel number!\n");
		return IZ_STOP_ERR;
	}

	if (cmd->argv[5]) {
		if (strcmp(cmd->argv[5], "short") ||
			cmd->argv[6])
			return IZ_STOP_ERR;
		else
			cap |= 1 << 7; /* Request short addr */
	}

	NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, chan);
	NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, pan_id);
	NLA_PUT_U8(msg, IEEE802154_ATTR_CAPABILITY, cap);

	return IZ_CONT_OK;

nla_put_failure:
	return IZ_STOP_ERR;
}
static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
{
	struct vlan_info *vi = link->l_info;
	struct nlattr *data;

	if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
		return nl_errno(ENOBUFS);

	if (vi->vi_mask & VLAN_HAS_ID)
		NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id);

	if (vi->vi_mask & VLAN_HAS_FLAGS) {
		struct ifla_vlan_flags flags = {
			.flags = vi->vi_flags,
			.mask = vi->vi_flags_mask,
		};

		NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags);
	}

	if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) {
		struct ifla_vlan_qos_mapping map;
		struct nlattr *qos;
		int i;

		if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
			goto nla_put_failure;

		for (i = 0; i <= VLAN_PRIO_MAX; i++) {
			if (vi->vi_ingress_qos[i]) {
				map.from = i;
				map.to = vi->vi_ingress_qos[i];

				NLA_PUT(msg, i, sizeof(map), &map);
			}
		}

		nla_nest_end(msg, qos);
	}

	if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
		struct ifla_vlan_qos_mapping map;
		struct nlattr *qos;
		int i;

		if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
			goto nla_put_failure;

		for (i = 0; i < vi->vi_negress; i++) {
			map.from = vi->vi_egress_qos[i].vm_from;
			map.to = vi->vi_egress_qos[i].vm_to;

			NLA_PUT(msg, i, sizeof(map), &map);
		}

		nla_nest_end(msg, qos);
	}

	nla_nest_end(msg, data);

nla_put_failure:

	return 0;
}

static struct rtnl_link_info_ops vlan_info_ops = {
	.io_name		= "vlan",
	.io_alloc		= vlan_alloc,
	.io_parse		= vlan_parse,
	.io_dump[NL_DUMP_BRIEF]	= vlan_dump_brief,
	.io_dump[NL_DUMP_FULL]	= vlan_dump_full,
	.io_clone		= vlan_clone,
	.io_put_attrs		= vlan_put_attrs,
	.io_free		= vlan_free,
};

int rtnl_link_vlan_set_id(struct rtnl_link *link, int id)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	vi->vi_vlan_id = id;
	vi->vi_mask |= VLAN_HAS_ID;

	return 0;
}

int rtnl_link_vlan_get_id(struct rtnl_link *link)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	if (vi->vi_mask & VLAN_HAS_ID)
		return vi->vi_vlan_id;
	else
		return 0;
}

int rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	vi->vi_flags_mask |= flags;
	vi->vi_flags |= flags;
	vi->vi_mask |= VLAN_HAS_FLAGS;

	return 0;
}

int rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	vi->vi_flags_mask |= flags;
	vi->vi_flags &= ~flags;
	vi->vi_mask |= VLAN_HAS_FLAGS;

	return 0;
}

unsigned int rtnl_link_vlan_get_flags(struct rtnl_link *link)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	return vi->vi_flags;
}

int rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from,
				   uint32_t to)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	if (from < 0 || from > VLAN_PRIO_MAX)
		return nl_error(EINVAL, "Invalid vlan prio 0..%d",
			VLAN_PRIO_MAX);

	vi->vi_ingress_qos[from] = to;
	vi->vi_mask |= VLAN_HAS_INGRESS_QOS;

	return 0;
}

uint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *link)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) {
		nl_error(EOPNOTSUPP, "Not a VLAN link");
		return NULL;
	}

	if (vi->vi_mask & VLAN_HAS_INGRESS_QOS)
		return vi->vi_ingress_qos;
	else
		return NULL;
}

int rtnl_link_vlan_set_egress_map(struct rtnl_link *link, uint32_t from, int to)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops)
		return nl_error(EOPNOTSUPP, "Not a VLAN link");

	if (to < 0 || to > VLAN_PRIO_MAX)
		return nl_error(EINVAL, "Invalid vlan prio 0..%d",
			VLAN_PRIO_MAX);

	if (vi->vi_negress >= vi->vi_egress_size) {
		int new_size = vi->vi_egress_size + 32;
		void *ptr;

		ptr = realloc(vi->vi_egress_qos, new_size);
		if (!ptr)
			return nl_errno(ENOMEM);

		vi->vi_egress_qos = ptr;
		vi->vi_egress_size = new_size;
	}

	vi->vi_egress_qos[vi->vi_negress].vm_from = from;
	vi->vi_egress_qos[vi->vi_negress].vm_to = to;
	vi->vi_negress++;
	vi->vi_mask |= VLAN_HAS_EGRESS_QOS;

	return 0;
}

struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *link,
					       int *negress)
{
	struct vlan_info *vi = link->l_info;

	if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) {
		nl_error(EOPNOTSUPP, "Not a VLAN link");
		return NULL;
	}

	if (negress == NULL) {
		nl_error(EINVAL, "Require pointer to store negress");
		return NULL;
	}

	if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
		*negress = vi->vi_negress;
		return vi->vi_egress_qos;
	} else {
		*negress = 0;
		return NULL;
	}
}

static void __init vlan_init(void)
{
	rtnl_link_register_info(&vlan_info_ops);
}

static void __exit vlan_exit(void)
{
	rtnl_link_unregister_info(&vlan_info_ops);
}
예제 #24
0
int
mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy,
					 IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
#define NLA_PUT(skb, attrtype, attrlen, data) \
	 do { \
		 if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \
			 printk("NLA PUT Error!!!!\n"); \
	 } while (0)

#define NLA_PUT_TYPE(skb, type, attrtype, value) \
	 do { \
		 type __tmp = value; \
		 NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \
	 } while (0)

#define NLA_PUT_U8(skb, attrtype, value) \
	 NLA_PUT_TYPE(skb, u8, attrtype, value)

#define NLA_PUT_U16(skb, attrtype, value) \
	 NLA_PUT_TYPE(skb, u16, attrtype, value)

#define NLA_PUT_U32(skb, attrtype, value) \
	 NLA_PUT_TYPE(skb, u32, attrtype, value)

#endif
	WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS;
	INT_32 i4Status = -EINVAL;
	UINT_32 u4BufLen;
	UINT_32 u4LinkScore;
	UINT_32 u4TotalError;
	UINT_32 u4TxExceedThresholdCount;
	UINT_32 u4TxTotalCount;

	P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL;
	PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics;
	struct sk_buff *skb;

	ASSERT(wiphy);
	ASSERT(prGlueInfo);

	if (data && len) {
		prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data;
	}

	if (!prParams->aucMacAddr) {
		DBGLOG(QM, TRACE, ("%s MAC Address is NULL\n", __func__));
		i4Status = -EINVAL;
		goto nla_put_failure;
	}

	skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1);

	if (!skb) {
		DBGLOG(QM, TRACE, ("%s allocate skb failed:\n", __func__));
		i4Status = -ENOMEM;
		goto nla_put_failure;
	}

	DBGLOG(QM, TRACE, ("Get [" MACSTR "] STA statistics\n", MAC2STR(prParams->aucMacAddr)));

	kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics));
	COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr);

	rStatus = kalIoctl(prGlueInfo,
			   wlanoidQueryStaStatistics,
			   &rQueryStaStatistics,
			   sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, TRUE, &u4BufLen);

	/* Calcute Link Score */
	u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount;
	u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount;
	u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount;

	/* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */
	/* u4LinkScore 0~9    , Drop packet ratio 0~9 and all packets exceed threshold */
	if (u4TxTotalCount) {
		if (u4TxExceedThresholdCount <= u4TxTotalCount) {
			u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount));
		} else {
			u4LinkScore = 0;
		}
	} else {
		u4LinkScore = 90;
	}

	u4LinkScore += 10;

	if (u4LinkScore == 10) {

		if (u4TotalError <= u4TxTotalCount) {
			u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount));
		} else {
			u4LinkScore = 0;
		}

	}

	if (u4LinkScore > 100) {
		u4LinkScore = 100;
	}


	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, NL80211_DRIVER_TESTMODE_VERSION);
	NLA_PUT(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr);
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, u4LinkScore);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, rQueryStaStatistics.u4Flag);

	/* FW part STA link status */
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_PER, rQueryStaStatistics.ucPer);
	NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, rQueryStaStatistics.ucRcpi);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, rQueryStaStatistics.u4PhyMode);
	NLA_PUT_U16(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, rQueryStaStatistics.u2LinkSpeed);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT,
		    rQueryStaStatistics.u4TxFailCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT,
		    rQueryStaStatistics.u4TxLifeTimeoutCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME,
		    rQueryStaStatistics.u4TxAverageAirTime);

	/* Driver part link status */
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT,
		    rQueryStaStatistics.u4TxTotalCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT,
		    rQueryStaStatistics.u4TxExceedThresholdCount);
	NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME,
		    rQueryStaStatistics.u4TxAverageProcessTime);

	/* Network counter */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY,
		sizeof(rQueryStaStatistics.au4TcResourceEmptyCount),
		rQueryStaStatistics.au4TcResourceEmptyCount);

	/* Sta queue length */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY,
		sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen);

	/* Global QM counter */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY,
		sizeof(rQueryStaStatistics.au4TcAverageQueLen),
		rQueryStaStatistics.au4TcAverageQueLen);

	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY,
		sizeof(rQueryStaStatistics.au4TcCurrentQueLen),
		rQueryStaStatistics.au4TcCurrentQueLen);

	/* Reserved field */
	NLA_PUT(skb,
		NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY,
		sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved);

	i4Status = cfg80211_testmode_reply(skb);

 nla_put_failure:
	return i4Status;
}