summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Dreier <roland@topspin.com>2003-01-06 09:06:34 -0800
committerDavid S. Miller <davem@kernel.bkbits.net>2003-01-06 09:06:34 -0800
commit4f85bc95dedb42855fe6ea88ec0353497997f964 (patch)
treee085c810ee0cea03102c67d5d6c4724a42635fa2
parentae4d98378f651581ece95d133fd65a811e5bb8d5 (diff)
[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.
-rw-r--r--include/linux/if_arp.h1
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--include/linux/rtnetlink.h1
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/rtnetlink.c66
5 files changed, 46 insertions, 28 deletions
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index dd936fe6180e..77906e130efd 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -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
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 513b89ca7836..b3026b172369 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 57296f48dc02..40ceec333586 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -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)
diff --git a/net/core/dev.c b/net/core/dev.c
index 72f606980694..3246a37067c5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1702d8aa0ad0..e324ae6f75f3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -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;