Example #1
0
static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
	struct ifinfomsg *ifm;
	struct nlattr *tb[IFLA_MAX+1];
	struct net_device *dev = NULL;
	struct sk_buff *nskb;
	char *iw_buf = NULL, *iw = NULL;
	int iw_buf_len = 0;
	int err;

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

	ifm = nlmsg_data(nlh);
	if (ifm->ifi_index >= 0) {
		dev = dev_get_by_index(ifm->ifi_index);
		if (dev == NULL)
			return -ENODEV;
	} else
		return -EINVAL;


#ifdef CONFIG_NET_WIRELESS_RTNETLINK
	if (tb[IFLA_WIRELESS]) {
		/* Call Wireless Extensions. We need to know the size before
		 * we can alloc. Various stuff checked in there... */
		err = wireless_rtnetlink_get(dev, nla_data(tb[IFLA_WIRELESS]),
					     nla_len(tb[IFLA_WIRELESS]),
					     &iw_buf, &iw_buf_len);
		if (err < 0)
			goto errout;

		iw += IW_EV_POINT_OFF;
	}
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

	nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
	if (nskb == NULL) {
		err = -ENOBUFS;
		goto errout;
	}

	err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
			       NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
	if (err < 0) {
		/* -EMSGSIZE implies BUG in if_nlmsg_size */
		WARN_ON(err == -EMSGSIZE);
		kfree_skb(nskb);
		goto errout;
	}
	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
errout:
	kfree(iw_buf);
	dev_put(dev);

	return err;
}
Example #2
0
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
{
    struct ifinfomsg  *ifm = NLMSG_DATA(in_nlh);
    struct rtattr    **ida = arg;
    struct net_device *dev;
    struct ifinfomsg *r;
    struct nlmsghdr  *nlh;
    int err = -ENOBUFS;
    struct sk_buff *skb;
    unsigned char	 *b;
    char *iw_buf = NULL;
    int iw_buf_len = 0;

    if (ifm->ifi_index >= 0)
        dev = dev_get_by_index(ifm->ifi_index);
    else
        return -EINVAL;
    if (!dev)
        return -ENODEV;

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

        /* Call Wireless Extensions. We need to know the size before
         * we can alloc. Various stuff checked in there... */
        err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
        if (err)
            goto out;
    }
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

    /* Create a skb big enough to include all the data.
     * Some requests are way bigger than 4k... Jean II */
    skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
                    GFP_KERNEL);
    if (!skb)
        goto out;
    b = skb->tail;

    /* Put in the message the usual good stuff */
    nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
                    RTM_NEWLINK, sizeof(*r));
    r = NLMSG_DATA(nlh);
    r->ifi_family = AF_UNSPEC;
    r->__ifi_pad = 0;
    r->ifi_type = dev->type;
    r->ifi_index = dev->ifindex;
    r->ifi_flags = dev->flags;
    r->ifi_change = 0;

    /* Put the wireless payload if it exist */
    if(iw_buf != NULL)
        RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
                iw_buf + IW_EV_POINT_OFF);

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

    /* Needed ? */
    NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

    err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
    if (err > 0)
        err = 0;
out:
    if(iw_buf != NULL)
        kfree(iw_buf);
    dev_put(dev);
    return err;

rtattr_failure:
nlmsg_failure:
    kfree_skb(skb);
    goto out;
}