Commit 4f85bc95 authored by Roland Dreier's avatar Roland Dreier Committed by David S. Miller

[NET]: Increase MAX_ADDR_LEN.

- Add ARPHRD_INFINIBAND
- Increase MAX_ADDR_LEN to 32 from 8
- Add suitable length protection to SIOCGIFHWADDR and friends.
- Add RTM_SETLINK for portably setting larger hw addrs.
parent ae4d9837
......@@ -40,6 +40,7 @@
#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */
#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */
#define ARPHRD_EUI64 27 /* EUI-64 */
#define ARPHRD_INFINIBAND 32 /* InfiniBand */
/* Dummy types for non ARP hardware */
#define ARPHRD_SLIP 256
......
......@@ -65,7 +65,7 @@ struct vlan_group;
#endif
#define MAX_ADDR_LEN 8 /* Largest hardware address length */
#define MAX_ADDR_LEN 32 /* Largest hardware address length */
/*
* Compute the worst case header length according to the protocols
......
......@@ -17,6 +17,7 @@
#define RTM_NEWLINK (RTM_BASE+0)
#define RTM_DELLINK (RTM_BASE+1)
#define RTM_GETLINK (RTM_BASE+2)
#define RTM_SETLINK (RTM_BASE+3)
#define RTM_NEWADDR (RTM_BASE+4)
#define RTM_DELADDR (RTM_BASE+5)
......
......@@ -2131,7 +2131,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
case SIOCGIFHWADDR:
memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
MAX_ADDR_LEN);
min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
ifr->ifr_hwaddr.sa_family = dev->type;
return 0;
......@@ -2152,7 +2152,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
if (ifr->ifr_hwaddr.sa_family != dev->type)
return -EINVAL;
memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
MAX_ADDR_LEN);
min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));
notifier_call_chain(&netdev_chain,
NETDEV_CHANGEADDR, dev);
return 0;
......
......@@ -220,6 +220,40 @@ int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct ifinfomsg *ifm = NLMSG_DATA(nlh);
struct rtattr **ida = arg;
struct net_device *dev;
int err;
dev = dev_get_by_index(ifm->ifi_index);
if (!dev)
return -ENODEV;
err = -EINVAL;
if (ida[IFLA_ADDRESS - 1]) {
if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
goto out;
memcpy(dev->dev_addr, RTA_DATA(ida[IFLA_ADDRESS - 1]),
dev->addr_len);
}
if (ida[IFLA_BROADCAST - 1]) {
if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len))
goto out;
memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
dev->addr_len);
}
err = 0;
out:
dev_put(dev);
return err;
}
int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx;
......@@ -457,33 +491,15 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
{
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, rtnetlink_dump_ifinfo, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, rtnetlink_dump_all, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, rtnetlink_dump_all, },
{ NULL, NULL, },
{ neigh_add, NULL, },
{ neigh_delete, NULL, },
{ NULL, neigh_dump_info, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, NULL, },
{ NULL, NULL, },
[RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
[RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
[RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
[RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
[RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info }
};
static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment