patch-2.1.79 linux/net/core/rtnetlink.c
Next file: linux/net/core/skbuff.c
Previous file: linux/net/core/profile.c
Back to the patch index
Back to the overall index
- Lines: 173
- Date:
Mon Jan 12 15:28:25 1998
- Orig file:
v2.1.78/linux/net/core/rtnetlink.c
- Orig date:
Mon Dec 1 12:04:16 1997
diff -u --recursive --new-file v2.1.78/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c
@@ -134,6 +134,22 @@
return 0;
}
+static int rtnetlink_get_ga(struct rtattr **rta, int sz,
+ struct rtattr *attr, int attrlen)
+{
+ while (RTA_OK(attr, attrlen)) {
+ int type = attr->rta_type;
+ if (type > 0) {
+ if (type > sz)
+ return -EINVAL;
+ rta[type-1] = attr;
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ return 0;
+}
+
+
void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
{
struct rtattr *rta;
@@ -150,6 +166,7 @@
{
struct ifinfomsg *r;
struct nlmsghdr *nlh;
+ unsigned char *b = skb->tail;
nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
@@ -168,9 +185,17 @@
r->ifi_qdisc = dev->qdisc_sleeping->handle;
if (dev->qdisc_sleeping->ops)
strcpy(r->ifi_qdiscname, dev->qdisc_sleeping->ops->id);
+ if (dev->get_stats) {
+ struct net_device_stats *stats = dev->get_stats(dev);
+ if (stats)
+ RTA_PUT(skb, IFLA_STATS, sizeof(*stats), stats);
+ }
+ nlh->nlmsg_len = skb->tail - b;
return skb->len;
nlmsg_failure:
+rtattr_failure:
+ skb_put(skb, b - skb->tail);
return -1;
}
@@ -191,10 +216,38 @@
return skb->len;
}
+int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx;
+ int s_idx = cb->family;
+
+ if (s_idx == 0)
+ s_idx = 1;
+ for (idx=1; idx<NPROTO; idx++) {
+ int type = cb->nlh->nlmsg_type-RTM_BASE;
+ if (idx < s_idx || idx == AF_PACKET)
+ continue;
+ if (rtnetlink_links[idx] == NULL ||
+ rtnetlink_links[idx][type].dumpit == NULL)
+ continue;
+ if (idx > s_idx)
+ memset(&cb->args[0], 0, sizeof(cb->args));
+ if (rtnetlink_links[idx][type].dumpit(skb, cb) == 0)
+ continue;
+ if (skb_tailroom(skb) < 256)
+ break;
+ }
+ cb->family = idx;
+
+ return skb->len;
+}
+
+
void rtmsg_ifinfo(int type, struct device *dev)
{
struct sk_buff *skb;
- int size = NLMSG_SPACE(sizeof(struct ifinfomsg));
+ int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+
+ RTA_LENGTH(sizeof(struct net_device_stats)));
skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
@@ -223,9 +276,11 @@
union {
struct kern_rta rta;
struct kern_ifa ifa;
+ struct rtattr *ga[RTA_MAX-1];
} u;
struct rtmsg *rtm;
struct ifaddrmsg *ifm;
+ struct ndmsg *ndm;
int exclusive = 0;
int family;
int type;
@@ -307,13 +362,22 @@
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifm))) < 0)
goto err_inval;
break;
-
- case RTM_NEWLINK:
- case RTM_DELLINK:
- case RTM_GETLINK:
case RTM_NEWNEIGH:
case RTM_DELNEIGH:
case RTM_GETNEIGH:
+ ndm = NLMSG_DATA(nlh);
+ if (nlh->nlmsg_len < sizeof(*ndm))
+ goto err_inval;
+
+ if (nlh->nlmsg_len > NLMSG_LENGTH(sizeof(*ndm)) &&
+ rtnetlink_get_ga(u.ga, NDA_MAX, NDA_RTA(ndm),
+ nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm))) < 0)
+ goto err_inval;
+ break;
+
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ case RTM_GETLINK:
/* Not urgent and even not necessary */
default:
goto err_inval;
@@ -399,6 +463,35 @@
rtnl_shunlock();
}
+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, },
+
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, neigh_dump_info, },
+ { NULL, NULL, },
+
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+ { NULL, NULL, },
+};
+
+
static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct device *dev = ptr;
@@ -429,6 +522,8 @@
if (rtnl == NULL)
panic("rtnetlink_init: cannot initialize rtnetlink\n");
register_netdevice_notifier(&rtnetlink_dev_notifier);
+ rtnetlink_links[AF_UNSPEC] = link_rtnetlink_table;
+ rtnetlink_links[AF_PACKET] = link_rtnetlink_table;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov