Exemple #1
0
static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
				  u32 seq, int flags, struct wpan_phy *phy)
{
	void *hdr;
	int i, pages = 0;
	uint32_t *buf = kcalloc(32, sizeof(uint32_t), GFP_KERNEL);

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

	if (!buf)
		return -EMSGSIZE;

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

	rtnl_lock();
	if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
	    nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
		goto nla_put_failure;
	for (i = 0; i < 32; i++) {
		if (phy->supported.channels[i])
			buf[pages++] = phy->supported.channels[i] | (i << 27);
	}
	if (pages &&
	    nla_put(msg, IEEE802154_ATTR_CHANNEL_PAGE_LIST,
		    pages * sizeof(uint32_t), buf))
		goto nla_put_failure;
	rtnl_unlock();
	kfree(buf);
	genlmsg_end(msg, hdr);
	return 0;

nla_put_failure:
	rtnl_unlock();
	genlmsg_cancel(msg, hdr);
out:
	kfree(buf);
	return -EMSGSIZE;
}
Exemple #2
0
static int __seg6_genl_dumphmac_element(struct seg6_hmac_info *hinfo,
					u32 portid, u32 seq, u32 flags,
					struct sk_buff *skb, u8 cmd)
{
	void *hdr;

	hdr = genlmsg_put(skb, portid, seq, &seg6_genl_family, flags, cmd);
	if (!hdr)
		return -ENOMEM;

	if (__seg6_hmac_fill_info(hinfo, skb) < 0)
		goto nla_put_failure;

	genlmsg_end(skb, hdr);
	return 0;

nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -EMSGSIZE;
}
Exemple #3
0
static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
	u32 seq, int flags, struct wpan_phy *phy)
{
	void *hdr;
	int i, pages = 0;
	uint32_t *buf = kzalloc(32 * sizeof(uint32_t), GFP_KERNEL);

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

	if (!buf)
		return -EMSGSIZE;

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

	mutex_lock(&phy->pib_lock);
	NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy));

	NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, phy->current_page);
	NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel);
	for (i = 0; i < 32; i++) {
		if (phy->channels_supported[i])
			buf[pages++] = phy->channels_supported[i] | (i << 27);
	}
	if (pages)
		NLA_PUT(msg, IEEE802154_ATTR_CHANNEL_PAGE_LIST,
				pages * sizeof(uint32_t), buf);

	mutex_unlock(&phy->pib_lock);
	kfree(buf);
	return genlmsg_end(msg, hdr);

nla_put_failure:
	mutex_unlock(&phy->pib_lock);
	genlmsg_cancel(msg, hdr);
out:
	kfree(buf);
	return -EMSGSIZE;
}
Exemple #4
0
int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
			       u8 comm_mode, u8 rf_mode)
{
	struct sk_buff *msg;
	void *hdr;

	pr_debug("DEP link is up\n");

	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
	if (!msg)
		return -ENOMEM;

	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_CMD_DEP_LINK_UP);
	if (!hdr)
		goto free_msg;

	if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
		goto nla_put_failure;
	if (rf_mode == NFC_RF_INITIATOR &&
	    nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx))
		goto nla_put_failure;
	if (nla_put_u8(msg, NFC_ATTR_COMM_MODE, comm_mode) ||
	    nla_put_u8(msg, NFC_ATTR_RF_MODE, rf_mode))
		goto nla_put_failure;

	genlmsg_end(msg, hdr);

	dev->dep_link_up = true;

	genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);

	return 0;

nla_put_failure:
	genlmsg_cancel(msg, hdr);
free_msg:
	nlmsg_free(msg);
	return -EMSGSIZE;
}
Exemple #5
0
static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
{
	struct net *net = genl_info_net(info);
	struct in6_addr *tun_src;
	struct sk_buff *msg;
	void *hdr;

	msg = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

	hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
			  &seg6_genl_family, 0, SEG6_CMD_GET_TUNSRC);
	if (!hdr)
		goto free_msg;

	rcu_read_lock();
	tun_src = rcu_dereference(seg6_pernet(net)->tun_src);

	if (nla_put(msg, SEG6_ATTR_DST, sizeof(struct in6_addr), tun_src))
		goto nla_put_failure;

	rcu_read_unlock();

	genlmsg_end(msg, hdr);
	genlmsg_reply(msg, info);

	return 0;

nla_put_failure:
	rcu_read_unlock();
	genlmsg_cancel(msg, hdr);
free_msg:
	nlmsg_free(msg);
	return -ENOMEM;
}
Exemple #6
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).portid, 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);

	if (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))
		goto nla_put_failure;
	if (target->nfcid1_len > 0 &&
	    nla_put(msg, NFC_ATTR_TARGET_NFCID1, target->nfcid1_len,
		    target->nfcid1))
		goto nla_put_failure;
	if (target->sensb_res_len > 0 &&
	    nla_put(msg, NFC_ATTR_TARGET_SENSB_RES, target->sensb_res_len,
		    target->sensb_res))
		goto nla_put_failure;
	if (target->sensf_res_len > 0 &&
	    nla_put(msg, NFC_ATTR_TARGET_SENSF_RES, target->sensf_res_len,
		    target->sensf_res))
		goto nla_put_failure;

	return genlmsg_end(msg, hdr);

nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}
static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
				    u32 seq, int flags, struct net_device *dev)
{
	void *hdr;
	struct wpan_phy *phy;
	struct ieee802154_mlme_ops *ops;
	__le16 short_addr, pan_id;

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

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

	ops = ieee802154_mlme_ops(dev);
	phy = dev->ieee802154_ptr->wpan_phy;
	BUG_ON(!phy);
	get_device(&phy->dev);

	short_addr = ops->get_short_addr(dev);
	pan_id = ops->get_pan_id(dev);

	if (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_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
	    nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
		goto nla_put_failure;

	if (ops->get_mac_params) {
		struct ieee802154_mac_params params;

		rtnl_lock();
		ops->get_mac_params(dev, &params);
		rtnl_unlock();

		if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
			       params.transmit_power) ||
		    nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) ||
		    nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE,
			       params.cca.mode) ||
		    nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL,
				params.cca_ed_level) ||
		    nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES,
			       params.csma_retries) ||
		    nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE,
			       params.min_be) ||
		    nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE,
			       params.max_be) ||
		    nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES,
			       params.frame_retries))
			goto nla_put_failure;
	}

	wpan_phy_put(phy);
	genlmsg_end(msg, hdr);
	return 0;

nla_put_failure:
	wpan_phy_put(phy);
	genlmsg_cancel(msg, hdr);
out:
	return -EMSGSIZE;
}
Exemple #8
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;
	struct l2tp_stats stats;
	unsigned int start;

	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);

	if (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) ||
	    (session->mru &&
	     nla_put_u16(skb, L2TP_ATTR_MRU, session->mru)))
		goto nla_put_failure;

	if ((session->ifname && session->ifname[0] &&
	     nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) ||
	    (session->cookie_len &&
	     nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len,
		     &session->cookie[0])) ||
	    (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
	    (((sk) && (sk->sk_policy[0] || sk->sk_policy[1])) &&
	     nla_put_u8(skb, L2TP_ATTR_USING_IPSEC, 1)) ||
#endif
	    (session->reorder_timeout &&
	     nla_put_msecs(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout)))
		goto nla_put_failure;

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

	do {
		start = u64_stats_fetch_begin(&session->stats.syncp);
		stats.tx_packets = session->stats.tx_packets;
		stats.tx_bytes = session->stats.tx_bytes;
		stats.tx_errors = session->stats.tx_errors;
		stats.rx_packets = session->stats.rx_packets;
		stats.rx_bytes = session->stats.rx_bytes;
		stats.rx_errors = session->stats.rx_errors;
		stats.rx_seq_discards = session->stats.rx_seq_discards;
		stats.rx_oos_packets = session->stats.rx_oos_packets;
	} while (u64_stats_fetch_retry(&session->stats.syncp, start));

	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
			stats.rx_seq_discards) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
			stats.rx_oos_packets) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors))
		goto nla_put_failure;
	nla_nest_end(skb, nest);

	return genlmsg_end(skb, hdr);

 nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}
Exemple #9
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;
#if IS_ENABLED(CONFIG_IPV6)
	struct ipv6_pinfo *np = NULL;
#endif
	struct l2tp_stats stats;
	unsigned int start;

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

	if (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))
		goto nla_put_failure;

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

	do {
		start = u64_stats_fetch_begin(&tunnel->stats.syncp);
		stats.tx_packets = tunnel->stats.tx_packets;
		stats.tx_bytes = tunnel->stats.tx_bytes;
		stats.tx_errors = tunnel->stats.tx_errors;
		stats.rx_packets = tunnel->stats.rx_packets;
		stats.rx_bytes = tunnel->stats.rx_bytes;
		stats.rx_errors = tunnel->stats.rx_errors;
		stats.rx_seq_discards = tunnel->stats.rx_seq_discards;
		stats.rx_oos_packets = tunnel->stats.rx_oos_packets;
	} while (u64_stats_fetch_retry(&tunnel->stats.syncp, start));

	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
			stats.rx_seq_discards) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
			stats.rx_oos_packets) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors))
		goto nla_put_failure;
	nla_nest_end(skb, nest);

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

#if IS_ENABLED(CONFIG_IPV6)
	if (sk->sk_family == AF_INET6)
		np = inet6_sk(sk);
#endif

	inet = inet_sk(sk);

	switch (tunnel->encap) {
	case L2TP_ENCAPTYPE_UDP:
		if (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)))
			goto nla_put_failure;
		/* NOBREAK */
	case L2TP_ENCAPTYPE_IP:
#if IS_ENABLED(CONFIG_IPV6)
		if (np) {
			if (nla_put(skb, L2TP_ATTR_IP6_SADDR, sizeof(np->saddr),
				    &np->saddr) ||
			    nla_put(skb, L2TP_ATTR_IP6_DADDR, sizeof(np->daddr),
				    &np->daddr))
				goto nla_put_failure;
		} else
#endif
		if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) ||
		    nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr))
			goto nla_put_failure;
		break;
	}

out:
	return genlmsg_end(skb, hdr);

nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}
Exemple #10
0
static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int flags,
				struct l2tp_session *session, u8 cmd)
{
	void *hdr;
	struct nlattr *nest;
	struct l2tp_tunnel *tunnel = session->tunnel;
	struct sock *sk = NULL;

	sk = tunnel->sock;

	hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, cmd);
	if (!hdr)
		return -EMSGSIZE;

	if (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) ||
	    (session->mru &&
	     nla_put_u16(skb, L2TP_ATTR_MRU, session->mru)))
		goto nla_put_failure;

	if ((session->ifname[0] &&
	     nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) ||
	    (session->cookie_len &&
	     nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len,
		     &session->cookie[0])) ||
	    (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
	    (((sk) && (sk->sk_policy[0] || sk->sk_policy[1])) &&
	     nla_put_u8(skb, L2TP_ATTR_USING_IPSEC, 1)) ||
#endif
	    (session->reorder_timeout &&
	     nla_put_msecs(skb, L2TP_ATTR_RECV_TIMEOUT, session->reorder_timeout)))
		goto nla_put_failure;

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

	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS,
		atomic_long_read(&session->stats.tx_packets)) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES,
		atomic_long_read(&session->stats.tx_bytes)) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS,
		atomic_long_read(&session->stats.tx_errors)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS,
		atomic_long_read(&session->stats.rx_packets)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES,
		atomic_long_read(&session->stats.rx_bytes)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
		atomic_long_read(&session->stats.rx_seq_discards)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
		atomic_long_read(&session->stats.rx_oos_packets)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS,
		atomic_long_read(&session->stats.rx_errors)))
		goto nla_put_failure;
	nla_nest_end(skb, nest);

	genlmsg_end(skb, hdr);
	return 0;

 nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}
Exemple #11
0
static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int flags,
			       struct l2tp_tunnel *tunnel, u8 cmd)
{
	void *hdr;
	struct nlattr *nest;
	struct sock *sk = NULL;
	struct inet_sock *inet;
#if IS_ENABLED(CONFIG_IPV6)
	struct ipv6_pinfo *np = NULL;
#endif

	hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags, cmd);
	if (!hdr)
		return -EMSGSIZE;

	if (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))
		goto nla_put_failure;

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

	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS,
		    atomic_long_read(&tunnel->stats.tx_packets)) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES,
		    atomic_long_read(&tunnel->stats.tx_bytes)) ||
	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS,
		    atomic_long_read(&tunnel->stats.tx_errors)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS,
		    atomic_long_read(&tunnel->stats.rx_packets)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES,
		    atomic_long_read(&tunnel->stats.rx_bytes)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
		    atomic_long_read(&tunnel->stats.rx_seq_discards)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
		    atomic_long_read(&tunnel->stats.rx_oos_packets)) ||
	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS,
		    atomic_long_read(&tunnel->stats.rx_errors)))
		goto nla_put_failure;
	nla_nest_end(skb, nest);

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

#if IS_ENABLED(CONFIG_IPV6)
	if (sk->sk_family == AF_INET6)
		np = inet6_sk(sk);
#endif

	inet = inet_sk(sk);

	switch (tunnel->encap) {
	case L2TP_ENCAPTYPE_UDP:
		if (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_tx))
			goto nla_put_failure;
		/* NOBREAK */
	case L2TP_ENCAPTYPE_IP:
#if IS_ENABLED(CONFIG_IPV6)
		if (np) {
			if (nla_put_in6_addr(skb, L2TP_ATTR_IP6_SADDR,
					     &np->saddr) ||
			    nla_put_in6_addr(skb, L2TP_ATTR_IP6_DADDR,
					     &sk->sk_v6_daddr))
				goto nla_put_failure;
		} else
#endif
		if (nla_put_in_addr(skb, L2TP_ATTR_IP_SADDR,
				    inet->inet_saddr) ||
		    nla_put_in_addr(skb, L2TP_ATTR_IP_DADDR,
				    inet->inet_daddr))
			goto nla_put_failure;
		break;
	}

out:
	genlmsg_end(skb, hdr);
	return 0;

nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}
Exemple #12
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);

	if (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))
		goto nla_put_failure;

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

	if (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))
		goto nla_put_failure;
	nla_nest_end(skb, nest);

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

	inet = inet_sk(sk);

	switch (tunnel->encap) {
	case L2TP_ENCAPTYPE_UDP:
		if (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)))
			goto nla_put_failure;
		/* NOBREAK */
	case L2TP_ENCAPTYPE_IP:
		if (nla_put_be32(skb, L2TP_ATTR_IP_SADDR, inet->inet_saddr) ||
		    nla_put_be32(skb, L2TP_ATTR_IP_DADDR, inet->inet_daddr))
			goto nla_put_failure;
		break;
	}

out:
	return genlmsg_end(skb, hdr);

nla_put_failure:
	genlmsg_cancel(skb, hdr);
	return -1;
}