/*
 *	Bridge netlink control interface
 *
 *	Authors:
 *	Stephen Hemminger		<shemminger@osdl.org>
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 */

#include <linux/kernel.h>
#include <linux/rtnetlink.h>
#include "br_private.h"

/*
 * Create one netlink message for one interface
 * Contains port and master info as well as carrier and bridge state.
 */
static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
			  u32 pid, u32 seq, int event, unsigned int flags)
{
	const struct net_bridge *br = port->br;
	const struct net_device *dev = port->dev;
	struct ifinfomsg *r;
	struct nlmsghdr *nlh;
	unsigned char *b = skb->tail;
	u32 mtu = dev->mtu;
	u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
	u8 portstate = port->state;

	pr_debug("br_fill_info event %d port %s master %s\n",
		 event, dev->name, br->dev->name);

	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
	r = NLMSG_DATA(nlh);
	r->ifi_family = AF_BRIDGE;
	r->__ifi_pad = 0;
	r->ifi_type = dev->type;
	r->ifi_index = dev->ifindex;
	r->ifi_flags = dev_get_flags(dev);
	r->ifi_change = 0;

	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);

	RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);

	if (dev->addr_len)
		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);

	RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
	if (dev->ifindex != dev->iflink)
		RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);


	RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);

	if (event == RTM_NEWLINK)
		RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);

	nlh->nlmsg_len = skb->tail - b;

	return skb->len;

nlmsg_failure:
rtattr_failure:

	skb_trim(skb, b - skb->data);
	return -EINVAL;
}

/*
 * Notify listeners of a change in port information
 */
void br_ifinfo_notify(int event, struct net_bridge_port *port)
{
	struct sk_buff *skb;
	int err = -ENOMEM;

	pr_debug("bridge notify event=%d\n", event);
	skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
			GFP_ATOMIC);
	if (!skb)
		goto err_out;

	err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
	if (err < 0)
		goto err_kfree;

	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
	netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
	return;

err_kfree:
	kfree_skb(skb);
err_out:
	netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
}

/*
 * Dump information about all ports, in response to GETLINK
 */
static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct net_device *dev;
	int idx;
	int s_idx = cb->args[0];
	int err = 0;

	read_lock(&dev_base_lock);
	for (dev = dev_base, idx = 0; dev; dev = dev->next) {
		struct net_bridge_port *p = dev->br_port;

		/* not a bridge port */
		if (!p)
			continue;

		if (idx < s_idx)
			goto cont;

		err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
				     cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
		if (err <= 0)
			break;
cont:
		++idx;
	}
	read_unlock(&dev_base_lock);

	cb->args[0] = idx;

	return skb->len;
}

/*
 * Change state of port (ie from forwarding to blocking etc)
 * Used by spanning tree in user space.
 */
static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
{
	struct rtattr  **rta = arg;
	struct ifinfomsg *ifm = NLMSG_DATA(nlh);
	struct net_device *dev;
	struct net_bridge_port *p;
	u8 new_state;

	if (ifm->ifi_family != AF_BRIDGE)
		return -EPFNOSUPPORT;

	/* Must pass valid state as PROTINFO */
	if (rta[IFLA_PROTINFO-1]) {
		u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
		new_state = *pstate;
	} else
		return -EINVAL;

	if (new_state > BR_STATE_BLOCKING)
		return -EINVAL;

	/* Find bridge port */
	dev = __dev_get_by_index(ifm->ifi_index);
	if (!dev)
		return -ENODEV;

	p = dev->br_port;
	if (!p)
		return -EINVAL;

	/* if kernel STP is running, don't allow changes */
	if (p->br->stp_enabled)
		return -EBUSY;

	if (!netif_running(dev))
		return -ENETDOWN;

	if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
		return -ENETDOWN;

	p->state = new_state;
	br_log_state(p);
	return 0;
}


static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = {
	[RTM_GETLINK - RTM_BASE] = { .dumpit	= br_dump_ifinfo, },
	[RTM_SETLINK - RTM_BASE] = { .doit      = br_rtm_setlink, },
};

void __init br_netlink_init(void)
{
	rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table;
}

void __exit br_netlink_fini(void)
{
	rtnetlink_links[PF_BRIDGE] = NULL;
}

