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; }
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; }