diff options
-rw-r--r-- | include/linux/if.h | 1 | ||||
-rw-r--r-- | include/linux/if_link.h | 1 | ||||
-rw-r--r-- | include/linux/netdevice.h | 3 | ||||
-rw-r--r-- | net/core/dev.c | 23 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 36 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 13 |
6 files changed, 77 insertions, 0 deletions
diff --git a/include/linux/if.h b/include/linux/if.h index 5c9d1fa93fef..65246846c844 100644 --- a/include/linux/if.h +++ b/include/linux/if.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/compiler.h> /* for "__user" et al */ | 24 | #include <linux/compiler.h> /* for "__user" et al */ |
25 | 25 | ||
26 | #define IFNAMSIZ 16 | 26 | #define IFNAMSIZ 16 |
27 | #define IFALIASZ 256 | ||
27 | #include <linux/hdlc/ioctl.h> | 28 | #include <linux/hdlc/ioctl.h> |
28 | 29 | ||
29 | /* Standard interface flags (netdevice->flags). */ | 30 | /* Standard interface flags (netdevice->flags). */ |
diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 84c3492ae5cb..f9032c88716a 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h | |||
@@ -79,6 +79,7 @@ enum | |||
79 | IFLA_LINKINFO, | 79 | IFLA_LINKINFO, |
80 | #define IFLA_LINKINFO IFLA_LINKINFO | 80 | #define IFLA_LINKINFO IFLA_LINKINFO |
81 | IFLA_NET_NS_PID, | 81 | IFLA_NET_NS_PID, |
82 | IFLA_IFALIAS, | ||
82 | __IFLA_MAX | 83 | __IFLA_MAX |
83 | }; | 84 | }; |
84 | 85 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 488c56e649b5..d675df08b946 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -471,6 +471,8 @@ struct net_device | |||
471 | char name[IFNAMSIZ]; | 471 | char name[IFNAMSIZ]; |
472 | /* device name hash chain */ | 472 | /* device name hash chain */ |
473 | struct hlist_node name_hlist; | 473 | struct hlist_node name_hlist; |
474 | /* snmp alias */ | ||
475 | char *ifalias; | ||
474 | 476 | ||
475 | /* | 477 | /* |
476 | * I/O specific fields | 478 | * I/O specific fields |
@@ -1224,6 +1226,7 @@ extern int dev_ethtool(struct net *net, struct ifreq *); | |||
1224 | extern unsigned dev_get_flags(const struct net_device *); | 1226 | extern unsigned dev_get_flags(const struct net_device *); |
1225 | extern int dev_change_flags(struct net_device *, unsigned); | 1227 | extern int dev_change_flags(struct net_device *, unsigned); |
1226 | extern int dev_change_name(struct net_device *, char *); | 1228 | extern int dev_change_name(struct net_device *, char *); |
1229 | extern int dev_set_alias(struct net_device *, const char *, size_t); | ||
1227 | extern int dev_change_net_namespace(struct net_device *, | 1230 | extern int dev_change_net_namespace(struct net_device *, |
1228 | struct net *, const char *); | 1231 | struct net *, const char *); |
1229 | extern int dev_set_mtu(struct net_device *, int); | 1232 | extern int dev_set_mtu(struct net_device *, int); |
diff --git a/net/core/dev.c b/net/core/dev.c index fdfc4b6a6448..e91390533999 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -954,6 +954,29 @@ rollback: | |||
954 | } | 954 | } |
955 | 955 | ||
956 | /** | 956 | /** |
957 | * dev_set_alias - change ifalias of a device | ||
958 | * @dev: device | ||
959 | * @alias: name up to IFALIASZ | ||
960 | * | ||
961 | * Set ifalias for a device, | ||
962 | */ | ||
963 | int dev_set_alias(struct net_device *dev, const char *alias, size_t len) | ||
964 | { | ||
965 | ASSERT_RTNL(); | ||
966 | |||
967 | if (len >= IFALIASZ) | ||
968 | return -EINVAL; | ||
969 | |||
970 | dev->ifalias = krealloc(dev->ifalias, len+1, GFP_KERNEL); | ||
971 | if (!dev->ifalias) | ||
972 | return -ENOMEM; | ||
973 | |||
974 | strlcpy(dev->ifalias, alias, len+1); | ||
975 | return len; | ||
976 | } | ||
977 | |||
978 | |||
979 | /** | ||
957 | * netdev_features_change - device changes features | 980 | * netdev_features_change - device changes features |
958 | * @dev: device to cause notification | 981 | * @dev: device to cause notification |
959 | * | 982 | * |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c1f4e0d428c0..92d6b9467314 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -209,9 +209,44 @@ static ssize_t store_tx_queue_len(struct device *dev, | |||
209 | return netdev_store(dev, attr, buf, len, change_tx_queue_len); | 209 | return netdev_store(dev, attr, buf, len, change_tx_queue_len); |
210 | } | 210 | } |
211 | 211 | ||
212 | static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, | ||
213 | const char *buf, size_t len) | ||
214 | { | ||
215 | struct net_device *netdev = to_net_dev(dev); | ||
216 | size_t count = len; | ||
217 | ssize_t ret; | ||
218 | |||
219 | if (!capable(CAP_NET_ADMIN)) | ||
220 | return -EPERM; | ||
221 | |||
222 | /* ignore trailing newline */ | ||
223 | if (len > 0 && buf[len - 1] == '\n') | ||
224 | --count; | ||
225 | |||
226 | rtnl_lock(); | ||
227 | ret = dev_set_alias(netdev, buf, count); | ||
228 | rtnl_unlock(); | ||
229 | |||
230 | return ret < 0 ? ret : len; | ||
231 | } | ||
232 | |||
233 | static ssize_t show_ifalias(struct device *dev, | ||
234 | struct device_attribute *attr, char *buf) | ||
235 | { | ||
236 | const struct net_device *netdev = to_net_dev(dev); | ||
237 | ssize_t ret = 0; | ||
238 | |||
239 | rtnl_lock(); | ||
240 | if (netdev->ifalias) | ||
241 | ret = sprintf(buf, "%s\n", netdev->ifalias); | ||
242 | rtnl_unlock(); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
212 | static struct device_attribute net_class_attributes[] = { | 246 | static struct device_attribute net_class_attributes[] = { |
213 | __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), | 247 | __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), |
214 | __ATTR(dev_id, S_IRUGO, show_dev_id, NULL), | 248 | __ATTR(dev_id, S_IRUGO, show_dev_id, NULL), |
249 | __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), | ||
215 | __ATTR(iflink, S_IRUGO, show_iflink, NULL), | 250 | __ATTR(iflink, S_IRUGO, show_iflink, NULL), |
216 | __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), | 251 | __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), |
217 | __ATTR(features, S_IRUGO, show_features, NULL), | 252 | __ATTR(features, S_IRUGO, show_features, NULL), |
@@ -418,6 +453,7 @@ static void netdev_release(struct device *d) | |||
418 | 453 | ||
419 | BUG_ON(dev->reg_state != NETREG_RELEASED); | 454 | BUG_ON(dev->reg_state != NETREG_RELEASED); |
420 | 455 | ||
456 | kfree(dev->ifalias); | ||
421 | kfree((char *)dev - dev->padded); | 457 | kfree((char *)dev - dev->padded); |
422 | } | 458 | } |
423 | 459 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 71edb8b36341..8862498fd4a6 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -586,6 +586,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
586 | { | 586 | { |
587 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 587 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
588 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | 588 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
589 | + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ | ||
589 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ | 590 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ |
590 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) | 591 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) |
591 | + nla_total_size(sizeof(struct rtnl_link_stats)) | 592 | + nla_total_size(sizeof(struct rtnl_link_stats)) |
@@ -640,6 +641,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
640 | if (txq->qdisc_sleeping) | 641 | if (txq->qdisc_sleeping) |
641 | NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id); | 642 | NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id); |
642 | 643 | ||
644 | if (dev->ifalias) | ||
645 | NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias); | ||
646 | |||
643 | if (1) { | 647 | if (1) { |
644 | struct rtnl_link_ifmap map = { | 648 | struct rtnl_link_ifmap map = { |
645 | .mem_start = dev->mem_start, | 649 | .mem_start = dev->mem_start, |
@@ -713,6 +717,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
713 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 717 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
714 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 718 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
715 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 719 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
720 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | ||
716 | }; | 721 | }; |
717 | 722 | ||
718 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 723 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
@@ -853,6 +858,14 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
853 | modified = 1; | 858 | modified = 1; |
854 | } | 859 | } |
855 | 860 | ||
861 | if (tb[IFLA_IFALIAS]) { | ||
862 | err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]), | ||
863 | nla_len(tb[IFLA_IFALIAS])); | ||
864 | if (err < 0) | ||
865 | goto errout; | ||
866 | modified = 1; | ||
867 | } | ||
868 | |||
856 | if (tb[IFLA_BROADCAST]) { | 869 | if (tb[IFLA_BROADCAST]) { |
857 | nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); | 870 | nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); |
858 | send_addr_notify = 1; | 871 | send_addr_notify = 1; |