示例#1
0
/*
 * Format up to a page worth of forwarding table entries
 * userbuf -- where to copy result
 * maxnum  -- maximum number of entries desired
 *            (limited to a page for sanity)
 * offset  -- number of records to skip
 */
static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf,
			       unsigned long maxnum, unsigned long offset)
{
	struct nlattr *attrs[BRC_GENL_A_MAX + 1];
	struct sk_buff *request, *reply;
	int retval;
	int len;

	/* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
	if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
		maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);

	request = brc_make_request(BRC_GENL_C_FDB_QUERY, dev->name, NULL);
	if (!request)
		return -ENOMEM;
	NLA_PUT_U64(request, BRC_GENL_A_FDB_COUNT, maxnum);
	NLA_PUT_U64(request, BRC_GENL_A_FDB_SKIP, offset);

	rtnl_unlock();
	reply = brc_send_command(request, attrs);
	retval = PTR_ERR(reply);
	if (IS_ERR(reply))
		goto exit;

	retval = -nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
	if (retval < 0)
		goto exit_free_skb;

	retval = -EINVAL;
	if (!attrs[BRC_GENL_A_FDB_DATA])
		goto exit_free_skb;
	len = nla_len(attrs[BRC_GENL_A_FDB_DATA]);
	if (len % sizeof(struct __fdb_entry) ||
	    len / sizeof(struct __fdb_entry) > maxnum)
		goto exit_free_skb;

	retval = len / sizeof(struct __fdb_entry);
	if (copy_to_user(userbuf, nla_data(attrs[BRC_GENL_A_FDB_DATA]), len))
		retval = -EFAULT;

exit_free_skb:
	kfree_skb(reply);
exit:
	rtnl_lock();
	return retval;

nla_put_failure:
	kfree_skb(request);
	return -ENOMEM;
}
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;
}
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
static int handle_interface_add(struct nl802154_state *state,
				struct nl_cb *cb,
				struct nl_msg *msg,
				int argc, char **argv,
				enum id_input id)
{
	char *name;
	enum nl802154_iftype type;
	uint64_t eui64 = 0;
	int tpset;

	if (argc < 1)
		return 1;

	name = argv[0];
	argc--;
	argv++;

	tpset = get_if_type(&argc, &argv, &type, true);
	if (tpset)
		return tpset;

	tpset = get_eui64(&argc, &argv, &eui64);
	if (tpset)
		return tpset;

	if (argc)
		return 1;

	NLA_PUT_STRING(msg, NL802154_ATTR_IFNAME, name);
	NLA_PUT_U32(msg, NL802154_ATTR_IFTYPE, type);
	NLA_PUT_U64(msg, NL802154_ATTR_EXTENDED_ADDR, eui64);

	return 0;

nla_put_failure:
	return -ENOBUFS;
}