Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 34421
b: refs/heads/master
c: da5e049
h: refs/heads/master
i:
  34419: 754c332
v: v3
  • Loading branch information
Thomas Graf authored and David S. Miller committed Sep 22, 2006
1 parent 3b15658 commit 0ebaf5f
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 92 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1823730fbc89fadde72a7bb3b7bdf03cc7b8835c
refs/heads/master: da5e0494c542dddc56a1f1edfd30310ea30f41ff
191 changes: 100 additions & 91 deletions trunk/net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,52 +336,69 @@ static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *c
return skb->len;
}

static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = {
[IFLA_IFNAME] = { .type = NLA_STRING },
[IFLA_MAP] = { .minlen = sizeof(struct rtnl_link_ifmap) },
[IFLA_MTU] = { .type = NLA_U32 },
[IFLA_TXQLEN] = { .type = NLA_U32 },
[IFLA_WEIGHT] = { .type = NLA_U32 },
[IFLA_OPERSTATE] = { .type = NLA_U8 },
[IFLA_LINKMODE] = { .type = NLA_U8 },
};

static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct ifinfomsg *ifm = NLMSG_DATA(nlh);
struct rtattr **ida = arg;
struct ifinfomsg *ifm;
struct net_device *dev;
int err, send_addr_notify = 0;
int err, send_addr_notify = 0, modified = 0;
struct nlattr *tb[IFLA_MAX+1];
char ifname[IFNAMSIZ];

err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
if (err < 0)
goto errout;

if (tb[IFLA_IFNAME] &&
nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ) >= IFNAMSIZ)
return -EINVAL;

err = -EINVAL;
ifm = nlmsg_data(nlh);
if (ifm->ifi_index >= 0)
dev = dev_get_by_index(ifm->ifi_index);
else if (ida[IFLA_IFNAME - 1]) {
char ifname[IFNAMSIZ];

if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
IFNAMSIZ) >= IFNAMSIZ)
return -EINVAL;
else if (tb[IFLA_IFNAME])
dev = dev_get_by_name(ifname);
} else
return -EINVAL;
else
goto errout;

if (!dev)
return -ENODEV;
if (dev == NULL) {
err = -ENODEV;
goto errout;
}

err = -EINVAL;
if (tb[IFLA_ADDRESS] &&
nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
goto errout_dev;

if (ifm->ifi_flags)
dev_change_flags(dev, ifm->ifi_flags);
if (tb[IFLA_BROADCAST] &&
nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
goto errout_dev;

if (ida[IFLA_MAP - 1]) {
if (tb[IFLA_MAP]) {
struct rtnl_link_ifmap *u_map;
struct ifmap k_map;

if (!dev->set_config) {
err = -EOPNOTSUPP;
goto out;
goto errout_dev;
}

if (!netif_device_present(dev)) {
err = -ENODEV;
goto out;
goto errout_dev;
}

if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
goto out;

u_map = RTA_DATA(ida[IFLA_MAP - 1]);

u_map = nla_data(tb[IFLA_MAP]);
k_map.mem_start = (unsigned long) u_map->mem_start;
k_map.mem_end = (unsigned long) u_map->mem_end;
k_map.base_addr = (unsigned short) u_map->base_addr;
Expand All @@ -390,119 +407,111 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
k_map.port = (unsigned char) u_map->port;

err = dev->set_config(dev, &k_map);
if (err < 0)
goto errout_dev;

if (err)
goto out;
modified = 1;
}

if (ida[IFLA_ADDRESS - 1]) {
if (tb[IFLA_ADDRESS]) {
struct sockaddr *sa;
int len;

if (!dev->set_mac_address) {
err = -EOPNOTSUPP;
goto out;
goto errout_dev;
}

if (!netif_device_present(dev)) {
err = -ENODEV;
goto out;
goto errout_dev;
}
if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
goto out;

len = sizeof(sa_family_t) + dev->addr_len;
sa = kmalloc(len, GFP_KERNEL);
if (!sa) {
err = -ENOMEM;
goto out;
goto errout_dev;
}
sa->sa_family = dev->type;
memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
dev->addr_len);
err = dev->set_mac_address(dev, sa);
kfree(sa);
if (err)
goto out;
goto errout_dev;
send_addr_notify = 1;
modified = 1;
}

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);
send_addr_notify = 1;
if (tb[IFLA_MTU]) {
err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
if (err < 0)
goto errout_dev;
modified = 1;
}

if (ida[IFLA_MTU - 1]) {
if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
goto out;
err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));

if (err)
goto out;

/*
* Interface selected by interface index but interface
* name provided implies that a name change has been
* requested.
*/
if (ifm->ifi_index >= 0 && ifname[0]) {
err = dev_change_name(dev, ifname);
if (err < 0)
goto errout_dev;
modified = 1;
}

if (ida[IFLA_TXQLEN - 1]) {
if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
goto out;
#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if (tb[IFLA_WIRELESS]) {
/* Call Wireless Extensions.
* Various stuff checked in there... */
err = wireless_rtnetlink_set(dev, nla_data(tb[IFLA_WIRELESS]),
nla_len(tb[IFLA_WIRELESS]));
if (err < 0)
goto errout_dev;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */

dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
if (tb[IFLA_BROADCAST]) {
nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
send_addr_notify = 1;
}

if (ida[IFLA_WEIGHT - 1]) {
if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
goto out;

dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
}
if (ifm->ifi_flags)
dev_change_flags(dev, ifm->ifi_flags);

if (ida[IFLA_OPERSTATE - 1]) {
if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
goto out;
if (tb[IFLA_TXQLEN])
dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);

set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1])));
}
if (tb[IFLA_WEIGHT])
dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);

if (ida[IFLA_LINKMODE - 1]) {
if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8)))
goto out;
if (tb[IFLA_OPERSTATE])
set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));

if (tb[IFLA_LINKMODE]) {
write_lock_bh(&dev_base_lock);
dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1]));
dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
write_unlock_bh(&dev_base_lock);
}

if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) {
char ifname[IFNAMSIZ];

if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1],
IFNAMSIZ) >= IFNAMSIZ)
goto out;
err = dev_change_name(dev, ifname);
if (err)
goto out;
}

#ifdef CONFIG_NET_WIRELESS_RTNETLINK
if (ida[IFLA_WIRELESS - 1]) {

/* Call Wireless Extensions.
* Various stuff checked in there... */
err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len);
if (err)
goto out;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */

err = 0;

out:
errout_dev:
if (err < 0 && modified && net_ratelimit())
printk(KERN_WARNING "A link change request failed with "
"some changes comitted already. Interface %s may "
"have been left with an inconsistent configuration, "
"please check.\n", dev->name);

if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);

dev_put(dev);
errout:
return err;
}

Expand Down Expand Up @@ -753,7 +762,7 @@ static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
.doit = do_getlink,
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
.dumpit = rtnetlink_dump_ifinfo },
[RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
[RTM_SETLINK - RTM_BASE] = { .doit = rtnl_setlink },
[RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
[RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
Expand Down

0 comments on commit 0ebaf5f

Please sign in to comment.