Begin of transformations to new netlink api
Subsystems (4)
PATCH 1/1 Begin of transformations to new netlink api
First batch of patches converting existing netlink code to use the new api. Fixing lots of unvalidated accesses to attributes.
PATCH 1/9 : Extend netlink messaging interface
Adds:
nlmsg_get_pos() return current position in message nlmsg_trim() trim part of message nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr nla_put_nohdr(skb, len, data) add attribute w/o hdr nla_find_nested() find attribute in nested attributes
Fixes nlmsg_new() to take allocation flags and consider size.
include/net/netlink.h +64 -10
@@ -35,6 +35,8 @@* nlmsg_put() add a netlink message to an skb * nlmsg_put_answer() callback based nlmsg_put() * nlmsg_end() finanlize netlink message +* nlmsg_get_pos() return current position in message +* nlmsg_trim() trim part of message * nlmsg_cancel() cancel message construction * nlmsg_free() free a netlink message *
@@ -80,8 +82,10 @@* struct nlattr netlink attribtue header * * Attribute Construction: -* nla_reserve(skb, type, len) reserve skb tailroom for an attribute +* nla_reserve(skb, type, len) reserve room for an attribute +* nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr * nla_put(skb, type, len, data) add attribute to skb +* nla_put_nohdr(skb, len, data) add attribute w/o hdr * * Attribute Construction for Basic Types: * nla_put_u8(skb, type, value) add u8 attribute to skb
@@ -139,6 +143,7 @@* nla_next(nla, remaining) get next netlink attribute * nla_validate() validate a stream of attributes * nla_find() find attribute in stream of attributes +* nla_find_nested() find attribute in nested attributes * nla_parse() parse and validate stream of attrs * nla_parse_nested() parse nested attribuets * nla_for_each_attr() loop over all attributes
@@ -203,12 +208,18 @@ extern int nla_memcmp(const struct nlatextern int nla_strcmp (const struct nlattr *nla,const char *str);extern struct nlattr *__nla_reserve (struct sk_buff *skb,int attrtype,int attrlen); +extern void *__nla_reserve_nohdr (struct sk_buff *skb,int attrlen);extern struct nlattr *nla_reserve (struct sk_buff *skb,int attrtype,int attrlen); +extern void *nla_reserve_nohdr (struct sk_buff *skb,int attrlen);extern void __nla_put (struct sk_buff *skb,int attrtype,int attrlen,const void *data); +extern void __nla_put_nohdr (struct sk_buff *skb,int attrlen, +const void *data);extern int nla_put (struct sk_buff *skb,int attrtype,int attrlen,const void *data); +extern int nla_put_nohdr (struct sk_buff *skb,int attrlen, +const void *data);/************************************************************************** * Netlink Messages
@@ -453,12 +464,13 @@ static inline struct nlmsghdr *nlmsg_put/** * nlmsg_new - Allocate a new netlink message * @size: maximum size of message +* @flags: the type of memory to allocate. * * Use NLMSG_GOODSIZE if size isn't know and you need a good default size. */ -static inline struct sk_buff *nlmsg_new (int size) +static inline struct sk_buff *nlmsg_new (int size,gfp_t flags) { -return alloc_skb (NLMSG_GOODSIZE ,GFP_KERNEL ); +return alloc_skb (size, flags); }/**
@@ -480,6 +492,32 @@ static inline int nlmsg_end(struct sk_bu }/** +* nlmsg_get_pos - return current position in netlink message +* @skb: socket buffer the message is stored in +* +* Returns a pointer to the current tail of the message. +*/ +static inline void *nlmsg_get_pos (struct sk_buff *skb) +{ +return skb->tail; +} + +/** +* nlmsg_trim - Trim message to a mark +* @skb: socket buffer the message is stored in +* @mark: mark to trim to +* +* Trims the message to the provided mark. Returns -1. +*/ +static inline int nlmsg_trim (struct sk_buff *skb,void *mark) +{ +if (mark) +skb_trim (skb, (unsigned char *) mark - skb->data); + +return -1 ; +} + +/** * nlmsg_cancel - Cancel construction of a netlink message * @skb: socket buffer the message is stored in * @nlh: netlink message header
@@ -489,9 +527,7 @@ static inline int nlmsg_end(struct sk_bu*/ static inline int nlmsg_cancel (struct sk_buff *skb,struct nlmsghdr *nlh) { -skb_trim (skb, (unsigned char *) nlh - skb->data); - -return -1 ; +return nlmsg_trim (skb, nlh); }/**
@@ -631,6 +667,18 @@ static inline struct nlattr *nla_next(co }/** +* nla_find_nested - find attribute in a set of nested attributes +* @nla: attribute containing the nested attributes +* @attrtype: type of attribute to look for +* +* Returns the first attribute which matches the specified type. +*/ +static inline struct nlattr *nla_find_nested (struct nlattr *nla,int attrtype) +{ +return nla_find (nla_data (nla),nla_len (nla), attrtype); +} + +/** * nla_parse_nested - parse nested attributes * @tb: destination array with maxtype+1 elements * @maxtype: maximum attribute type to be expected
@@ -862,10 +910,7 @@ static inline int nla_nest_end(struct sk*/ static inline int nla_nest_cancel (struct sk_buff *skb,struct nlattr *start) { -if (start) -skb_trim (skb, (unsigned char *) start - skb->data); - -return -1 ; +return nlmsg_trim (skb, start); }/**
@@ -880,4 +925,13 @@ static inline int nla_nest_cancel(structnla_ok (pos, rem); \ pos = nla_next(pos, &(rem))) +/** +* nla_for_each_nested - iterate over nested attributes +* @pos: loop counter, set to current attribute +* @nla: attribute containing the nested attributes +* @rem: initialized to len, holds bytes currently remaining in stream +*/ +#define nla_for_each_nested (pos, nla, rem) \ + nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem) +#endif
net/netlink/attr.c +75 -0
108 lines not on this page · raw message
kernel/taskstats.c +1 -1
@@ -75,7 +75,7 @@ static int prepare_reply(struct genl_inf/* * If new attributes are added, please revisit this allocation */ - skb =nlmsg_new (size); + skb =nlmsg_new (size,GFP_KERNEL );if (!skb)return -ENOMEM ;
net/netlink/genetlink.c +1 -1
@@ -440,7 +440,7 @@ static struct sk_buff *ctrl_build_msg(ststruct sk_buff *skb;int err; - skb =nlmsg_new (NLMSG_GOODSIZE ); + skb =nlmsg_new (NLMSG_GOODSIZE ,GFP_KERNEL );if (skb ==NULL )return ERR_PTR (-ENOBUFS );
PATCH 2/9 : Convert core netlink handling to new netlink api
In reply to Thomas GrafFixes a theoretical memory and locking leak when the size of the netlink header would exceed the skb tailroom.
net/netlink/af_netlink.c +22 -19
@@ -1147,7 +1147,7 @@ static int netlink_sendmsg(struct kiocbif (len > sk->sk_sndbuf -32 ) goto out; err = -ENOBUFS ; - skb =alloc_skb (len,GFP_KERNEL ); + skb =nlmsg_new (len,GFP_KERNEL );if (skb==NULL ) goto out;
@@ -1342,19 +1342,18 @@ static int netlink_dump(struct sock *sk)struct netlink_callback *cb;struct sk_buff *skb;struct nlmsghdr *nlh; -int len; +int len, err = -ENOBUFS ; skb =sock_rmalloc (sk,NLMSG_GOODSIZE ,0 ,GFP_KERNEL );if (!skb) -return -ENOBUFS ; + goto errout;spin_lock (&nlk->cb_lock); cb = nlk->cb;if (cb ==NULL ) { -spin_unlock (&nlk->cb_lock); -kfree_skb (skb); -return -EINVAL ; + err = -EINVAL ; + goto errout_skb; } len = cb->dump (skb, cb);
@@ -1366,8 +1365,12 @@ static int netlink_dump(struct sock *sk)return 0 ; } - nlh =NLMSG_NEW_ANSWER (skb, cb,NLMSG_DONE ,sizeof (len),NLM_F_MULTI ); -memcpy (NLMSG_DATA (nlh), &len,sizeof (len)); + nlh =nlmsg_put_answer (skb, cb,NLMSG_DONE ,sizeof (len),NLM_F_MULTI ); +if (!nlh) + goto errout_skb; + +memcpy (nlmsg_data (nlh), &len,sizeof (len)); +skb_queue_tail (&sk->sk_receive_queue, skb); sk->sk_data_ready (sk, skb->len);
@@ -1379,8 +1382,11 @@ static int netlink_dump(struct sock *sk)netlink_destroy_callback (cb);return 0 ; -nlmsg_failure: -return -ENOBUFS ; +errout_skb: +spin_unlock (&nlk->cb_lock); +kfree_skb (skb); +errout: +return err; } int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
@@ -1432,11 +1438,11 @@ void netlink_ack(struct sk_buff *in_skb,int size;if (err ==0 ) - size =NLMSG_SPACE (sizeof (struct nlmsgerr )); + size =nlmsg_total_size (sizeof (*errmsg));else - size =NLMSG_SPACE (4 +NLMSG_ALIGN (nlh->nlmsg_len)); + size =nlmsg_total_size (sizeof (*errmsg) +nlmsg_len (nlh)); - skb =alloc_skb (size,GFP_KERNEL ); + skb =nlmsg_new (size,GFP_KERNEL );if (!skb) {struct sock *sk;
@@ -1452,16 +1458,15 @@ void netlink_ack(struct sk_buff *in_skb, rep =__nlmsg_put (skb,NETLINK_CB (in_skb).pid, nlh->nlmsg_seq,NLMSG_ERROR ,sizeof (struct nlmsgerr ),0 ); - errmsg =NLMSG_DATA (rep); + errmsg =nlmsg_data (rep); errmsg->error = err; -memcpy (&errmsg->msg, nlh, err ? nlh->nlmsg_len :sizeof (struct nlmsghdr )); +memcpy (&errmsg->msg, nlh, err ? nlh->nlmsg_len :sizeof (*nlh));netlink_unicast (in_skb->sk, skb,NETLINK_CB (in_skb).pid,MSG_DONTWAIT ); }static int netlink_rcv_skb (struct sk_buff *skb,int (*cb)(struct sk_buff *,struct nlmsghdr *,int *)) { -unsigned int total_len;struct nlmsghdr *nlh;int err;
@@ -1471,8 +1476,6 @@ static int netlink_rcv_skb(struct sk_bufif (nlh->nlmsg_len <NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)return 0 ; - total_len =min (NLMSG_ALIGN (nlh->nlmsg_len), skb->len); -if (cb (skb, nlh, &err) <0 ) {/* Not an error, but we have to interrupt processing * here. Note: that in this case we do not pull
@@ -1484,7 +1487,7 @@ static int netlink_rcv_skb(struct sk_buf }else if (nlh->nlmsg_flags &NLM_F_ACK )netlink_ack (skb, nlh,0 ); -skb_pull (skb, total_len); +netlink_queue_skip (nlh, skb); }return 0 ;
PATCH 3/9 : Convert address addition to new netlink api
In reply to Thomas GrafAdds rtm_to_ifaddr() transforming a netlink message to a struct in_ifaddr. Fixes various unvalidated netlink attributes causing memory corruptions when left empty by userspace applications.
net/ipv4/devinet.c +75 -33
@@ -62,6 +62,7 @@#include <net/ip.h> #include <net/route.h> #include <net/ip_fib.h> +#include <net/netlink.h> struct ipv4_devconf ipv4_devconf = { .accept_redirects =1 ,
@@ -78,6 +79,14 @@ static struct ipv4_devconf ipv4_devconf_ .accept_source_route = 1, }; +static struct nla_policy ifa_ipv4_policy[IFA_MAX +1 ]__read_mostly = { + [IFA_LOCAL ] = { .type =NLA_U32 }, + [IFA_ADDRESS ] = { .type =NLA_U32 }, + [IFA_BROADCAST ] = { .type =NLA_U32 }, + [IFA_ANYCAST ] = { .type =NLA_U32 }, + [IFA_LABEL ] = { .type =NLA_STRING }, +}; +static void rtmsg_ifa (int event,struct in_ifaddr *);static BLOCKING_NOTIFIER_HEAD (inetaddr_chain);
@@ -451,57 +460,90 @@ out:return -EADDRNOTAVAIL ; } -static int inet_rtm_newaddr (struct sk_buff *skb,struct nlmsghdr *nlh,void *arg) +static struct in_ifaddr *rtm_to_ifaddr (struct nlmsghdr *nlh) { -struct rtattr **rta = arg; +struct nlattr *tb[IFA_MAX +1 ]; +struct in_ifaddr *ifa; +struct ifaddrmsg *ifm;struct net_device *dev;struct in_device *in_dev; -struct ifaddrmsg *ifm =NLMSG_DATA (nlh); -struct in_ifaddr *ifa; -int rc = -EINVAL ; +int err = -EINVAL ; -ASSERT_RTNL (); + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv4_policy); +if (err <0 ) + goto errout; -if (ifm->ifa_prefixlen >32 || !rta[IFA_LOCAL -1 ]) - goto out; + ifm =nlmsg_data (nlh); +if (ifm->ifa_prefixlen >32 || tb[IFA_LOCAL ] ==NULL ) + goto errout; - rc = -ENODEV ; -if ((dev =__dev_get_by_index (ifm->ifa_index)) ==NULL ) - goto out; + dev =__dev_get_by_index (ifm->ifa_index); +if (dev ==NULL ) { + err = -ENODEV ; + goto errout; + } - rc = -ENOBUFS ; -if ((in_dev =__in_dev_get_rtnl (dev)) ==NULL ) { + in_dev =__in_dev_get_rtnl (dev); +if (in_dev ==NULL ) { in_dev =inetdev_init (dev); -if (!in_dev) - goto out; +if (in_dev ==NULL ) { + err = -ENOBUFS ; + goto errout; + } } -if ((ifa =inet_alloc_ifa ()) ==NULL ) - goto out; + ifa =inet_alloc_ifa (); +if (ifa ==NULL ) { +/* +* A potential indev allocation can be left alive, it stays +* assigned to its device and is destroy with it. +*/ + err = -ENOBUFS ; + goto errout; + } + +in_dev_hold (in_dev); + +if (tb[IFA_ADDRESS ] ==NULL ) + tb[IFA_ADDRESS ] = tb[IFA_LOCAL ]; -if (!rta[IFA_ADDRESS -1 ]) - rta[IFA_ADDRESS -1 ] = rta[IFA_LOCAL -1 ]; -memcpy (&ifa->ifa_local,RTA_DATA (rta[IFA_LOCAL -1 ]),4 ); -memcpy (&ifa->ifa_address,RTA_DATA (rta[IFA_ADDRESS -1 ]),4 ); ifa->ifa_prefixlen = ifm->ifa_prefixlen; ifa->ifa_mask =inet_make_mask (ifm->ifa_prefixlen); -if (rta[IFA_BROADCAST -1 ]) -memcpy (&ifa->ifa_broadcast, -RTA_DATA (rta[IFA_BROADCAST -1 ]),4 ); -if (rta[IFA_ANYCAST -1 ]) -memcpy (&ifa->ifa_anycast,RTA_DATA (rta[IFA_ANYCAST -1 ]),4 ); ifa->ifa_flags = ifm->ifa_flags; ifa->ifa_scope = ifm->ifa_scope; -in_dev_hold (in_dev); - ifa->ifa_dev = in_dev; -if (rta[IFA_LABEL -1 ]) -rtattr_strlcpy (ifa->ifa_label, rta[IFA_LABEL -1 ],IFNAMSIZ ); + ifa->ifa_dev = in_dev; + + ifa->ifa_local =nla_get_u32 (tb[IFA_LOCAL ]); + ifa->ifa_address =nla_get_u32 (tb[IFA_ADDRESS ]); + +if (tb[IFA_BROADCAST ]) + ifa->ifa_broadcast =nla_get_u32 (tb[IFA_BROADCAST ]); + +if (tb[IFA_ANYCAST ]) + ifa->ifa_anycast =nla_get_u32 (tb[IFA_ANYCAST ]); + +if (tb[IFA_LABEL ]) +nla_strlcpy (ifa->ifa_label, tb[IFA_LABEL ],IFNAMSIZ );else memcpy (ifa->ifa_label, dev->name,IFNAMSIZ ); - rc =inet_insert_ifa (ifa); -out: -return rc; +return ifa; + +errout: +return ERR_PTR (err); +} + +static int inet_rtm_newaddr (struct sk_buff *skb,struct nlmsghdr *nlh,void *arg) +{ +struct in_ifaddr *ifa; + +ASSERT_RTNL (); + + ifa =rtm_to_ifaddr (nlh); +if (IS_ERR (ifa)) +return PTR_ERR (ifa); + +return inet_insert_ifa (ifa); }/*
PATCH 4/9 : Convert address deletion to new netlink api
In reply to Thomas GrafFixes various unvalidated netlink attributes causing memory corruptions when left empty by userspace.
net/ipv4/devinet.c +29 -15
@@ -430,34 +430,48 @@ struct in_ifaddr *inet_ifa_byprefix(strustatic int inet_rtm_deladdr (struct sk_buff *skb,struct nlmsghdr *nlh,void *arg) { -struct rtattr **rta = arg; +struct nlattr *tb[IFA_MAX +1 ];struct in_device *in_dev; -struct ifaddrmsg *ifm =NLMSG_DATA (nlh); +struct ifaddrmsg *ifm;struct in_ifaddr *ifa, **ifap; +int err = -EINVAL ;ASSERT_RTNL (); -if ((in_dev =inetdev_by_index (ifm->ifa_index)) ==NULL ) - goto out; + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv4_policy); +if (err <0 ) + goto errout; + + ifm =nlmsg_data (nlh); + in_dev =inetdev_by_index (ifm->ifa_index); +if (in_dev ==NULL ) { + err = -ENODEV ; + goto errout; + } +__in_dev_put (in_dev);for (ifap = &in_dev->ifa_list; (ifa = *ifap) !=NULL ; ifap = &ifa->ifa_next) { -if ((rta[IFA_LOCAL -1 ] && -memcmp (RTA_DATA (rta[IFA_LOCAL -1 ]), - &ifa->ifa_local,4 )) || - (rta[IFA_LABEL -1 ] && -rtattr_strcmp (rta[IFA_LABEL -1 ], ifa->ifa_label)) || - (rta[IFA_ADDRESS -1 ] && - (ifm->ifa_prefixlen != ifa->ifa_prefixlen || - !inet_ifa_match (*(u32 *)RTA_DATA (rta[IFA_ADDRESS -1 ]), - ifa)))) +if (tb[IFA_LOCAL ] && + ifa->ifa_local !=nla_get_u32 (tb[IFA_LOCAL ]))continue ; + +if (tb[IFA_LABEL ] &&nla_strcmp (tb[IFA_LABEL ], ifa->ifa_label)) +continue ; + +if (tb[IFA_ADDRESS ] && + (ifm->ifa_prefixlen != ifa->ifa_prefixlen || + !inet_ifa_match (nla_get_u32 (tb[IFA_ADDRESS ]), ifa))) +continue ; +inet_del_ifa (in_dev, ifap,1 );return 0 ; } -out: -return -EADDRNOTAVAIL ; + + err = -EADDRNOTAVAIL ; +errout: +return err; }static struct in_ifaddr *rtm_to_ifaddr (struct nlmsghdr *nlh)
PATCH 5/9 : Convert address dumping to new netlink api
In reply to Thomas Grafnet/ipv4/devinet.c +23 -19
@@ -1112,32 +1112,37 @@ static int inet_fill_ifaddr(struct sk_bu {struct ifaddrmsg *ifm;struct nlmsghdr *nlh; -unsigned char *b = skb->tail; - nlh =NLMSG_NEW (skb, pid, seq, event,sizeof (*ifm), flags); - ifm =NLMSG_DATA (nlh); + nlh =nlmsg_put (skb, pid, seq, event,sizeof (*ifm), flags); +if (nlh ==NULL ) +return -ENOBUFS ; + + ifm =nlmsg_data (nlh); ifm->ifa_family =AF_INET ; ifm->ifa_prefixlen = ifa->ifa_prefixlen; ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT ; ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; +if (ifa->ifa_address) -RTA_PUT (skb,IFA_ADDRESS ,4 , &ifa->ifa_address); +NLA_PUT_U32 (skb,IFA_ADDRESS , ifa->ifa_address); +if (ifa->ifa_local) -RTA_PUT (skb,IFA_LOCAL ,4 , &ifa->ifa_local); +NLA_PUT_U32 (skb,IFA_LOCAL , ifa->ifa_local); +if (ifa->ifa_broadcast) -RTA_PUT (skb,IFA_BROADCAST ,4 , &ifa->ifa_broadcast); +NLA_PUT_U32 (skb,IFA_BROADCAST , ifa->ifa_broadcast); +if (ifa->ifa_anycast) -RTA_PUT (skb,IFA_ANYCAST ,4 , &ifa->ifa_anycast); +NLA_PUT_U32 (skb,IFA_ANYCAST , ifa->ifa_anycast); +if (ifa->ifa_label[0 ]) -RTA_PUT (skb,IFA_LABEL ,IFNAMSIZ , &ifa->ifa_label); - nlh->nlmsg_len = skb->tail - b; -return skb->len; +NLA_PUT_STRING (skb,IFA_LABEL , ifa->ifa_label); + +return nlmsg_end (skb, nlh); -nlmsg_failure: -rtattr_failure: -skb_trim (skb, b - skb->data); -return -1 ; +nla_put_failure: +return nlmsg_cancel (skb, nlh); }static int inet_dump_ifaddr (struct sk_buff *skb,struct netlink_callback *cb)
@@ -1185,17 +1190,16 @@ done:static void rtmsg_ifa (int event,struct in_ifaddr * ifa) { -int size =NLMSG_SPACE (sizeof (struct ifaddrmsg ) +128 ); -struct sk_buff *skb =alloc_skb (size,GFP_KERNEL ); +struct sk_buff *skb; -if (!skb) + skb =nlmsg_new (NLMSG_GOODSIZE ,GFP_KERNEL ); +if (skb ==NULL )netlink_set_err (rtnl,0 ,RTNLGRP_IPV4_IFADDR ,ENOBUFS );else if (inet_fill_ifaddr (skb, ifa,0 ,0 , event,0 ) <0 ) {kfree_skb (skb);netlink_set_err (rtnl,0 ,RTNLGRP_IPV4_IFADDR ,EINVAL ); - }else { + }else netlink_broadcast (rtnl, skb,0 ,RTNLGRP_IPV4_IFADDR ,GFP_KERNEL ); - } }static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES ] = {
PATCH 6/9 : Move interface address bits to linux/if_addr.h
In reply to Thomas Grafinclude/linux/if_addr.h new file +53 -0
@@ -0,0 +1,53 @@ +#ifndef __LINUX_IF_ADDR_H +#define __LINUX_IF_ADDR_H + +#include <linux/netlink.h> + +struct ifaddrmsg +{ +__u8 ifa_family; +__u8 ifa_prefixlen;/* The prefix length */ +__u8 ifa_flags;/* Flags */ +__u8 ifa_scope;/* Address scope */ +__u32 ifa_index;/* Link index */ +}; + +/* +* Important comment: +* IFA_ADDRESS is prefix address, rather than local interface address. +* It makes no difference for normally configured broadcast interfaces, +* but for point-to-point IFA_ADDRESS is DESTINATION address, +* local address is supplied in IFA_LOCAL attribute. +*/ +enum +{ +IFA_UNSPEC , +IFA_ADDRESS , +IFA_LOCAL , +IFA_LABEL , +IFA_BROADCAST , +IFA_ANYCAST , +IFA_CACHEINFO , +IFA_MULTICAST , + __IFA_MAX, +}; + +#define IFA_MAX (__IFA_MAX - 1) + +/* ifa_flags */ +#define IFA_F_SECONDARY 0x01 +#define IFA_F_TEMPORARY IFA_F_SECONDARY + +#define IFA_F_DEPRECATED 0x20 +#define IFA_F_TENTATIVE 0x40 +#define IFA_F_PERMANENT 0x80 + +struct ifa_cacheinfo +{ +__u32 ifa_prefered; +__u32 ifa_valid; +__u32 cstamp;/* created timestamp, hundredths of seconds */ +__u32 tstamp;/* updated timestamp, hundredths of seconds */ +}; + +#endif
net/decnet/dn_dev.c +1 -0
@@ -34,6 +34,7 @@#include <linux/seq_file.h> #include <linux/timer.h> #include <linux/string.h> +#include <linux/if_addr.h> #include <linux/if_arp.h> #include <linux/if_ether.h> #include <linux/skbuff.h>
net/ipv4/devinet.c +1 -0
@@ -43,6 +43,7 @@#include <linux/in.h> #include <linux/errno.h> #include <linux/interrupt.h> +#include <linux/if_addr.h> #include <linux/if_ether.h> #include <linux/inet.h> #include <linux/netdevice.h>
net/ipv4/fib_frontend.c +1 -0
@@ -32,6 +32,7 @@#include <linux/inet.h> #include <linux/inetdevice.h> #include <linux/netdevice.h> +#include <linux/if_addr.h> #include <linux/if_arp.h> #include <linux/skbuff.h> #include <linux/netlink.h>
net/ipv6/addrconf.c +1 -0
@@ -48,6 +48,7 @@#include <linux/net.h> #include <linux/in6.h> #include <linux/netdevice.h> +#include <linux/if_addr.h> #include <linux/if_arp.h> #include <linux/if_arcnet.h> #include <linux/if_infiniband.h>
net/ipv6/ndisc.c +1 -0
@@ -62,6 +62,7 @@#include <linux/sysctl.h> #endif +#include <linux/if_addr.h> #include <linux/if_arp.h> #include <linux/ipv6.h> #include <linux/icmpv6.h>
net/core/rtnetlink.c +1 -0
@@ -35,6 +35,7 @@#include <linux/init.h> #include <linux/security.h> #include <linux/mutex.h> +#include <linux/if_addr.h> #include <asm/uaccess.h> #include <asm/system.h>
include/linux/rtnetlink.h +0 -56
62 lines not on this page · raw message
PATCH 7/9 : Convert link modification to new netlink api
In reply to Thomas GrafTransforms do_setlink() into rtnl_setlink() using the new netlink api. A warning message printed to the console is added in the event that a change request fails while part of the change request has been comitted already. The ioctl() based nature of net devices makes it almost impossible to move on to atomic netlink operations without obsoleting some of the functionality.
net/core/rtnetlink.c +101 -93
@@ -336,52 +336,69 @@ static int rtnetlink_dump_ifinfo(structreturn 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;
@@ -390,106 +407,97 @@ static int do_setlink(struct sk_buff *sk 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 ]) {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; - err = dev->set_mac_address (dev,RTA_DATA (ida[IFLA_ADDRESS -1 ])); -if (err) - goto out; + err = dev->set_mac_address (dev,nla_data (tb[IFLA_ADDRESS ])); +if (err <0 ) + 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 ; + } + +/* +* 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_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; - +#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 */ -if (ida[IFLA_TXQLEN -1 ]) { -if (ida[IFLA_TXQLEN -1 ]->rta_len !=RTA_LENGTH (sizeof (u32))) - goto out; - - 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; }
@@ -740,7 +748,7 @@ static struct rtnetlink_link link_rtnetl .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 },
PATCH 8/9 : Convert link dumping to new netlink api
In reply to Thomas GrafTransforms netlink code to dump link tables to use the new netlink api. Makes rtnl_getlink() available regardless of the availability of the wireless extensions.
Adding copy_rtnl_link_stats() avoids the structural dependency of struct rtnl_link_stats on struct net_device_stats and thus avoids troubles later on.
net/core/rtnetlink.c +136 -143
@@ -218,41 +218,73 @@ static void set_operstate(struct net_dev } } -static int rtnetlink_fill_ifinfo (struct sk_buff *skb,struct net_device *dev, -int type,u32 pid,u32 seq,u32 change, -unsigned int flags) -{ -struct ifinfomsg *r; -struct nlmsghdr *nlh; -unsigned char *b = skb->tail; - - nlh =NLMSG_NEW (skb, pid, seq, type,sizeof (*r), flags); - 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_get_flags (dev); - r->ifi_change = change; +static void copy_rtnl_link_stats (struct rtnl_link_stats *a, +struct net_device_stats *b) +{ + a->rx_packets = b->rx_packets; + a->tx_packets = b->tx_packets; + a->rx_bytes = b->rx_bytes; + a->tx_bytes = b->tx_bytes; + a->rx_errors = b->rx_errors; + a->tx_errors = b->tx_errors; + a->rx_dropped = b->rx_dropped; + a->tx_dropped = b->tx_dropped; + + a->multicast = b->multicast; + a->collisions = b->collisions; + + a->rx_length_errors = b->rx_length_errors; + a->rx_over_errors = b->rx_over_errors; + a->rx_crc_errors = b->rx_crc_errors; + a->rx_frame_errors = b->rx_frame_errors; + a->rx_fifo_errors = b->rx_fifo_errors; + a->rx_missed_errors = b->rx_missed_errors; + + a->tx_aborted_errors = b->tx_aborted_errors; + a->tx_carrier_errors = b->tx_carrier_errors; + a->tx_fifo_errors = b->tx_fifo_errors; + a->tx_heartbeat_errors = b->tx_heartbeat_errors; + a->tx_window_errors = b->tx_window_errors; -RTA_PUT (skb,IFLA_IFNAME ,strlen (dev->name)+1 , dev->name); + a->rx_compressed = b->rx_compressed; + a->tx_compressed = b->tx_compressed; +}; -if (1 ) { -u32 txqlen = dev->tx_queue_len; -RTA_PUT (skb,IFLA_TXQLEN ,sizeof (txqlen), &txqlen); - } +static int rtnl_fill_ifinfo (struct sk_buff *skb,struct net_device *dev, +void *iwbuf,int iwbuflen,int type,u32 pid, +u32 seq,u32 change,unsigned int flags) +{ +struct ifinfomsg *ifm; +struct nlmsghdr *nlh; -if (1 ) { -u32 weight = dev->weight; -RTA_PUT (skb,IFLA_WEIGHT ,sizeof (weight), &weight); - } + nlh =nlmsg_put (skb, pid, seq, type,sizeof (*ifm), flags); +if (nlh ==NULL ) +return -ENOBUFS ; -if (1 ) { -u8 operstate =netif_running (dev)?dev->operstate:IF_OPER_DOWN ; -u8 link_mode = dev->link_mode; -RTA_PUT (skb,IFLA_OPERSTATE ,sizeof (operstate), &operstate); -RTA_PUT (skb,IFLA_LINKMODE ,sizeof (link_mode), &link_mode); - } + ifm =nlmsg_data (nlh); + ifm->ifi_family =AF_UNSPEC ; + ifm->__ifi_pad =0 ; + ifm->ifi_type = dev->type; + ifm->ifi_index = dev->ifindex; + ifm->ifi_flags =dev_get_flags (dev); + ifm->ifi_change = change; + +NLA_PUT_STRING (skb,IFLA_IFNAME , dev->name); +NLA_PUT_U32 (skb,IFLA_TXQLEN , dev->tx_queue_len); +NLA_PUT_U32 (skb,IFLA_WEIGHT , dev->weight); +NLA_PUT_U8 (skb,IFLA_OPERSTATE , +netif_running (dev) ? dev->operstate :IF_OPER_DOWN ); +NLA_PUT_U8 (skb,IFLA_LINKMODE , dev->link_mode); +NLA_PUT_U32 (skb,IFLA_MTU , dev->mtu); + +if (dev->ifindex != dev->iflink) +NLA_PUT_U32 (skb,IFLA_LINK , dev->iflink); + +if (dev->master) +NLA_PUT_U32 (skb,IFLA_MASTER , dev->master->ifindex); + +if (dev->qdisc_sleeping) +NLA_PUT_STRING (skb,IFLA_QDISC , dev->qdisc_sleeping->ops->id);if (1 ) { struct rtnl_link_ifmap map = {
@@ -263,58 +295,38 @@ static int rtnetlink_fill_ifinfo(struct .dma = dev->dma, .port = dev->if_port, }; -RTA_PUT (skb,IFLA_MAP ,sizeof (map), &map); +NLA_PUT (skb,IFLA_MAP ,sizeof (map), &map); }if (dev->addr_len) { -RTA_PUT (skb,IFLA_ADDRESS , dev->addr_len, dev->dev_addr); -RTA_PUT (skb,IFLA_BROADCAST , dev->addr_len, dev->broadcast); - } - -if (1 ) { -u32 mtu = dev->mtu; -RTA_PUT (skb,IFLA_MTU ,sizeof (mtu), &mtu); - } - -if (dev->ifindex != dev->iflink) { -u32 iflink = dev->iflink; -RTA_PUT (skb,IFLA_LINK ,sizeof (iflink), &iflink); - } - -if (dev->qdisc_sleeping) -RTA_PUT (skb,IFLA_QDISC , -strlen (dev->qdisc_sleeping->ops->id) +1 , - dev->qdisc_sleeping->ops->id); - -if (dev->master) { -u32 master = dev->master->ifindex; -RTA_PUT (skb,IFLA_MASTER ,sizeof (master), &master); +NLA_PUT (skb,IFLA_ADDRESS , dev->addr_len, dev->dev_addr); +NLA_PUT (skb,IFLA_BROADCAST , dev->addr_len, dev->broadcast); }if (dev->get_stats) { -unsigned long *stats = (unsigned long *)dev->get_stats (dev); +struct net_device_stats *stats = dev->get_stats (dev);if (stats) { -struct rtattr *a; -__u32 *s; -int i; -int n =sizeof (struct rtnl_link_stats )/4 ; - - a =__RTA_PUT (skb,IFLA_STATS , n*4 ); - s =RTA_DATA (a); -for (i=0 ; i<n; i++) - s[i] = stats[i]; +struct nlattr *attr; + + attr =nla_reserve (skb,IFLA_STATS , +sizeof (struct rtnl_link_stats )); +if (attr ==NULL ) + goto nla_put_failure; + +copy_rtnl_link_stats (nla_data (attr), stats); } } - nlh->nlmsg_len = skb->tail - b; -return skb->len; -nlmsg_failure: -rtattr_failure: -skb_trim (skb, b - skb->data); -return -1 ; +if (iwbuf) +NLA_PUT (skb,IFLA_WIRELESS , iwbuflen, iwbuf); + +return nlmsg_end (skb, nlh); + +nla_put_failure: +return nlmsg_cancel (skb, nlh); } -static int rtnetlink_dump_ifinfo (struct sk_buff *skb,struct netlink_callback *cb) +static int rtnl_dump_ifinfo (struct sk_buff *skb,struct netlink_callback *cb) {int idx;int s_idx = cb->args[0 ];
@@ -324,10 +336,9 @@ static int rtnetlink_dump_ifinfo(structfor (dev=dev_base, idx=0 ; dev; dev = dev->next, idx++) {if (idx < s_idx)continue ; -if (rtnetlink_fill_ifinfo (skb, dev,RTM_NEWLINK , -NETLINK_CB (cb->skb).pid, - cb->nlh->nlmsg_seq,0 , -NLM_F_MULTI ) <=0 ) +if (rtnl_fill_ifinfo (skb, dev,NULL ,0 ,RTM_NEWLINK , +NETLINK_CB (cb->skb).pid, + cb->nlh->nlmsg_seq,0 ,NLM_F_MULTI ) <=0 )break ; }read_unlock (&dev_base_lock);
@@ -501,84 +512,69 @@ errout:return err; } -#ifdef CONFIG_NET_WIRELESS_RTNETLINK -static int do_getlink (struct sk_buff *in_skb,struct nlmsghdr * in_nlh,void *arg) +static int rtnl_getlink (struct sk_buff *skb,struct nlmsghdr * 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 ; +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, payload; -if (ifm->ifi_index >=0 ) + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFLA_MAX , ifla_policy); +if (err <0 ) + goto errout; + + ifm =nlmsg_data (nlh); +if (ifm->ifi_index >=0 ) { dev =dev_get_by_index (ifm->ifi_index); -else +if (dev ==NULL ) +return -ENODEV ; + }else return -EINVAL ; -if (!dev) -return -ENODEV ; -#ifdef CONFIG_NET_WIRELESS_RTNETLINK -if (ida[IFLA_WIRELESS -1 ]) { +#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,RTA_DATA (ida[IFLA_WIRELESS -1 ]), ida[IFLA_WIRELESS -1 ]->rta_len, &iw_buf, &iw_buf_len); -if (err) - goto out; + 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 */ -/* 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; + payload =NLMSG_ALIGN (sizeof (struct ifinfomsg ) + +nla_total_size (iw_buf_len)); + nskb =nlmsg_new (nlmsg_total_size (payload),GFP_KERNEL ); +if (nskb ==NULL ) { + err = -ENOBUFS ; + goto errout; + } -/* Needed ? */ -NETLINK_CB (skb).dst_pid =NETLINK_CB (in_skb).pid; + err =rtnl_fill_ifinfo (nskb, dev, iw, iw_buf_len,RTM_NEWLINK , +NETLINK_CB (skb).pid, nlh->nlmsg_seq,0 ,0 ); +if (err <=0 ) { +kfree_skb (skb); + goto errout; + } - err =netlink_unicast (rtnl, skb,NETLINK_CB (in_skb).pid,MSG_DONTWAIT ); + err =netlink_unicast (rtnl, skb,NETLINK_CB (skb).pid,MSG_DONTWAIT );if (err >0 ) err =0 ; -out: -if (iw_buf !=NULL ) -kfree (iw_buf); +errout: +kfree (iw_buf);dev_put (dev); -return err; -rtattr_failure: -nlmsg_failure: -kfree_skb (skb); - goto out; +return err; } -#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ -static int rtnetlink_dump_all (struct sk_buff *skb,struct netlink_callback *cb) +static int rtnl_dump_all (struct sk_buff *skb,struct netlink_callback *cb) {int idx;int s_idx = cb->family;
@@ -609,11 +605,11 @@ void rtmsg_ifinfo(int type, struct net_dsizeof (struct rtnl_link_ifmap ) + sizeof(struct rtnl_link_stats) + 128); - skb =alloc_skb (size,GFP_KERNEL ); + skb =nlmsg_new (size,GFP_KERNEL );if (!skb)return ; -if (rtnetlink_fill_ifinfo (skb, dev, type,0 ,0 , change,0 ) <0 ) { +if (rtnl_fill_ifinfo (skb, dev,NULL ,0 , type,0 ,0 , change,0 ) <0 ) {kfree_skb (skb);return ; }
@@ -743,14 +739,11 @@ static void rtnetlink_rcv(struct sock *sstatic struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES ] = { - [RTM_GETLINK -RTM_BASE ] = { -#ifdef CONFIG_NET_WIRELESS_RTNETLINK - .doit = do_getlink, -#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ - .dumpit = rtnetlink_dump_ifinfo }, + [RTM_GETLINK -RTM_BASE ] = { .doit = rtnl_getlink, + .dumpit = rtnl_dump_ifinfo }, [RTM_SETLINK -RTM_BASE ] = { .doit = rtnl_setlink }, - [RTM_GETADDR -RTM_BASE ] = { .dumpit = rtnetlink_dump_all }, - [RTM_GETROUTE -RTM_BASE ] = { .dumpit = rtnetlink_dump_all }, + [RTM_GETADDR -RTM_BASE ] = { .dumpit = rtnl_dump_all }, + [RTM_GETROUTE -RTM_BASE ] = { .dumpit = rtnl_dump_all }, [RTM_NEWNEIGH -RTM_BASE ] = { .doit = neigh_add }, [RTM_DELNEIGH -RTM_BASE ] = { .doit = neigh_delete }, [RTM_GETNEIGH -RTM_BASE ] = { .dumpit = neigh_dump_info },
@@ -758,7 +751,7 @@ static struct rtnetlink_link link_rtnetl [RTM_NEWRULE - RTM_BASE] = { .doit = fib_nl_newrule }, [RTM_DELRULE - RTM_BASE] = { .doit = fib_nl_delrule }, #endif - [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, + [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnl_dump_all }, [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info }, [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set }, };
PATCH 9/9 : Move netlink interface bits to linux/if.h
In reply to Thomas Grafinclude/linux/if.h +129 -0
@@ -212,5 +212,134 @@ struct ifconf#define ifc_buf ifc_ifcu.ifcu_buf/* buffer address */ #define ifc_req ifc_ifcu.ifcu_req/* array of structures */ +/* The struct should be in sync with struct net_device_stats */ +struct rtnl_link_stats +{ +__u32 rx_packets;/* total packets received */ +__u32 tx_packets;/* total packets transmitted */ +__u32 rx_bytes;/* total bytes received */ +__u32 tx_bytes;/* total bytes transmitted */ +__u32 rx_errors;/* bad packets received */ +__u32 tx_errors;/* packet transmit problems */ +__u32 rx_dropped;/* no space in linux buffers */ +__u32 tx_dropped;/* no space available in linux */ +__u32 multicast;/* multicast packets received */ +__u32 collisions; + +/* detailed rx_errors: */ +__u32 rx_length_errors; +__u32 rx_over_errors;/* receiver ring buff overflow */ +__u32 rx_crc_errors;/* recved pkt with crc error */ +__u32 rx_frame_errors;/* recv'd frame alignment error */ +__u32 rx_fifo_errors;/* recv'r fifo overrun */ +__u32 rx_missed_errors;/* receiver missed packet */ + +/* detailed tx_errors */ +__u32 tx_aborted_errors; +__u32 tx_carrier_errors; +__u32 tx_fifo_errors; +__u32 tx_heartbeat_errors; +__u32 tx_window_errors; + +/* for cslip etc */ +__u32 rx_compressed; +__u32 tx_compressed; +}; + +/* The struct should be in sync with struct ifmap */ +struct rtnl_link_ifmap +{ +__u64 mem_start; +__u64 mem_end; +__u64 base_addr; +__u16 irq; +__u8 dma; +__u8 port; +}; + +enum +{ +IFLA_UNSPEC , +IFLA_ADDRESS , +IFLA_BROADCAST , +IFLA_IFNAME , +IFLA_MTU , +IFLA_LINK , +IFLA_QDISC , +IFLA_STATS , +IFLA_COST , +#define IFLA_COST IFLA_COST + IFLA_PRIORITY, +#define IFLA_PRIORITY IFLA_PRIORITY + IFLA_MASTER, +#define IFLA_MASTER IFLA_MASTER + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ +#define IFLA_WIRELESS IFLA_WIRELESS + IFLA_PROTINFO, /* Protocol specific information for a link */ +#define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP + IFLA_WEIGHT, +#define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, +IFLA_LINKMODE , + __IFLA_MAX +}; + + +#define IFLA_MAX (__IFLA_MAX - 1) + +/* ifi_flags. + +IFF_* flags. + +The only change is: +IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are +more not changeable by user. They describe link media +characteristics and set by device driver. + +Comments: +- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid +- If neither of these three flags are set; +the interface is NBMA. + +- IFF_MULTICAST does not mean anything special: +multicasts can be used on all not-NBMA links. +IFF_MULTICAST means that this media uses special encapsulation +for multicast frames. Apparently, all IFF_POINTOPOINT and +IFF_BROADCAST devices are able to use multicasts too. +*/ + +/* IFLA_LINK. +For usual devices it is equal ifi_index. +If it is a "virtual interface" (f.e. tunnel), ifi_link +can point to real physical interface (f.e. for bandwidth calculations), +or maybe 0, what means, that real media is unknown (usual +for IPIP tunnels, when route to endpoint is allowed to change) +*/ + +/* Subtype attributes for IFLA_PROTINFO */ +enum +{ +IFLA_INET6_UNSPEC , +IFLA_INET6_FLAGS ,/* link flags */ +IFLA_INET6_CONF ,/* sysctl parameters */ +IFLA_INET6_STATS ,/* statistics */ +IFLA_INET6_MCAST ,/* MC things. What of them? */ +IFLA_INET6_CACHEINFO ,/* time values and max reasm size */ + __IFLA_INET6_MAX +}; + +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + +struct ifla_cacheinfo +{ +__u32 max_reasm_len; +__u32 tstamp;/* ipv6InterfaceTable updated timestamp */ +__u32 reachable_time; +__u32 retrans_time; +};#endif /* _LINUX_IF_H */
include/linux/rtnetlink.h +1 -132
145 lines not on this page · raw message
Re: [PATCH 9/9] [NET]: Move netlink interface bits to linux/if.h
Quoted 155 lines · Thomas Graf
Signed-off-by Thomas Graf <[email protected]>Index:
net-2.6.19/include/linux/if.h
===================================================================include/linux/if.h +129
-0@@ -212,5 +212,134 @@ struct ifconf#define ifc_buf ifc_ifcu.ifcu_buf/* buffer address */ #define ifc_req ifc_ifcu.ifcu_req/* array of structures */ +/* The struct should be in sync with struct net_device_stats */ +struct rtnl_link_stats +{ +__u32 rx_packets;/* total packets received */ +__u32 tx_packets;/* total packets transmitted */ +__u32 rx_bytes;/* total bytes received */ +__u32 tx_bytes;/* total bytes transmitted */ +__u32 rx_errors;/* bad packets received */ +__u32 tx_errors;/* packet transmit problems */ +__u32 rx_dropped;/* no space in linux buffers */ +__u32 tx_dropped;/* no space available in linux */ +__u32 multicast;/* multicast packets received */ +__u32 collisions; + +/* detailed rx_errors: */ +__u32 rx_length_errors; +__u32 rx_over_errors;/* receiver ring buff overflow */ +__u32 rx_crc_errors;/* recved pkt with crc error */ +__u32 rx_frame_errors;/* recv'd frame alignment error */ +__u32 rx_fifo_errors;/* recv'r fifo overrun */ +__u32 rx_missed_errors;/* receiver missed packet */ + +/* detailed tx_errors */ +__u32 tx_aborted_errors; +__u32 tx_carrier_errors; +__u32 tx_fifo_errors; +__u32 tx_heartbeat_errors; +__u32 tx_window_errors; + +/* for cslip etc */ +__u32 rx_compressed; +__u32 tx_compressed; +}; + +/* The struct should be in sync with struct ifmap */ +struct rtnl_link_ifmap +{ +__u64 mem_start; +__u64 mem_end; +__u64 base_addr; +__u16 irq; +__u8 dma; +__u8 port; +}; + +enum +{ +IFLA_UNSPEC , +IFLA_ADDRESS , +IFLA_BROADCAST , +IFLA_IFNAME , +IFLA_MTU , +IFLA_LINK , +IFLA_QDISC , +IFLA_STATS , +IFLA_COST , +#define IFLA_COST IFLA_COST + IFLA_PRIORITY, +#define IFLA_PRIORITY IFLA_PRIORITY + IFLA_MASTER, +#define IFLA_MASTER IFLA_MASTER + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ +#define IFLA_WIRELESS IFLA_WIRELESS + IFLA_PROTINFO, /* Protocol specific information for a link */ +#define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP + IFLA_WEIGHT, +#define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, +IFLA_LINKMODE , + __IFLA_MAX +}; + + +#define IFLA_MAX (__IFLA_MAX - 1) + +/* ifi_flags. + +IFF_* flags. + +The only change is: +IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are +more not changeable by user. They describe link media +characteristics and set by device driver. + +Comments: +- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid +- If neither of these three flags are set; +the interface is NBMA. + +- IFF_MULTICAST does not mean anything special: +multicasts can be used on all not-NBMA links. +IFF_MULTICAST means that this media uses special encapsulation +for multicast frames. Apparently, all IFF_POINTOPOINT and +IFF_BROADCAST devices are able to use multicasts too. +*/ + +/* IFLA_LINK. +For usual devices it is equal ifi_index. +If it is a "virtual interface" (f.e. tunnel), ifi_link +can point to real physical interface (f.e. for bandwidth calculations), +or maybe 0, what means, that real media is unknown (usual +for IPIP tunnels, when route to endpoint is allowed to change) +*/ + +/* Subtype attributes for IFLA_PROTINFO */ +enum +{ +IFLA_INET6_UNSPEC , +IFLA_INET6_FLAGS ,/* link flags */ +IFLA_INET6_CONF ,/* sysctl parameters */ +IFLA_INET6_STATS ,/* statistics */ +IFLA_INET6_MCAST ,/* MC things. What of them? */ +IFLA_INET6_CACHEINFO ,/* time values and max reasm size */ + __IFLA_INET6_MAX +}; + +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + +struct ifla_cacheinfo +{ +__u32 max_reasm_len; +__u32 tstamp;/* ipv6InterfaceTable updated timestamp */ +__u32 reachable_time; +__u32 retrans_time; +};#endif /* _LINUX_IF_H */ Index:
net-2.6.19/include/linux/rtnetlink.h
===================================================================include/linux/rtnetlink.h +1
-0@@ -2,6 +2,7 @@#define __LINUX_RTNETLINK_H#include <linux/netlink.h> +#include <linux/if.h> /**** * Routing/neighbour discovery messages. @@ -607,138 +608,6 @@ struct prefix_cacheinfo__u32 valid_time;
include/linux/rtnetlink.h struct prefix_cacheinfo · line 611
Quoted 10 lines
include/linux/rtnetlink.h +0
-7}; -/* The struct should be in sync with struct net_device_stats */ -struct rtnl_link_stats -{ -__u32 rx_packets;/* total packets received */ -__u32 tx_packets;/* total packets transmitted */ -__u32 rx_bytes;/* total bytes received */ -__u32 tx_bytes;/* total bytes transmitted */
Make the packets and byte counts __u64 so if/when we extend net_device stats to bigger values, the message format doesn't have to change.
Quoted 134 lines
include/linux/rtnetlink.h +0
-125-__u32 rx_errors;/* bad packets received */ -__u32 tx_errors;/* packet transmit problems */ -__u32 rx_dropped;/* no space in linux buffers */ -__u32 tx_dropped;/* no space available in linux */ -__u32 multicast;/* multicast packets received */ -__u32 collisions; - -/* detailed rx_errors: */ -__u32 rx_length_errors; -__u32 rx_over_errors;/* receiver ring buff overflow */ -__u32 rx_crc_errors;/* recved pkt with crc error */ -__u32 rx_frame_errors;/* recv'd frame alignment error */ -__u32 rx_fifo_errors;/* recv'r fifo overrun */ -__u32 rx_missed_errors;/* receiver missed packet */ - -/* detailed tx_errors */ -__u32 tx_aborted_errors; -__u32 tx_carrier_errors; -__u32 tx_fifo_errors; -__u32 tx_heartbeat_errors; -__u32 tx_window_errors; - -/* for cslip etc */ -__u32 rx_compressed; -__u32 tx_compressed; -}; - -/* The struct should be in sync with struct ifmap */ -struct rtnl_link_ifmap -{ -__u64 mem_start; -__u64 mem_end; -__u64 base_addr; -__u16 irq; -__u8 dma; -__u8 port; -}; - -enum -{ -IFLA_UNSPEC , -IFLA_ADDRESS , -IFLA_BROADCAST , -IFLA_IFNAME , -IFLA_MTU , -IFLA_LINK , -IFLA_QDISC , -IFLA_STATS , -IFLA_COST , -#define IFLA_COST IFLA_COST - IFLA_PRIORITY, -#define IFLA_PRIORITY IFLA_PRIORITY - IFLA_MASTER, -#define IFLA_MASTER IFLA_MASTER - IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ -#define IFLA_WIRELESS IFLA_WIRELESS - IFLA_PROTINFO, /* Protocol specific information for a link */ -#define IFLA_PROTINFO IFLA_PROTINFO - IFLA_TXQLEN, -#define IFLA_TXQLEN IFLA_TXQLEN - IFLA_MAP, -#define IFLA_MAP IFLA_MAP - IFLA_WEIGHT, -#define IFLA_WEIGHT IFLA_WEIGHT - IFLA_OPERSTATE, -IFLA_LINKMODE , - __IFLA_MAX -}; - - -#define IFLA_MAX (__IFLA_MAX - 1) - -#define IFLA_RTA (r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) -#define IFLA_PAYLOAD (n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) - -/* ifi_flags. - -IFF_* flags. - -The only change is: -IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are -more not changeable by user. They describe link media -characteristics and set by device driver. - -Comments: -- Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid -- If neither of these three flags are set; -the interface is NBMA. - -- IFF_MULTICAST does not mean anything special: -multicasts can be used on all not-NBMA links. -IFF_MULTICAST means that this media uses special encapsulation -for multicast frames. Apparently, all IFF_POINTOPOINT and -IFF_BROADCAST devices are able to use multicasts too. -*/ - -/* IFLA_LINK. -For usual devices it is equal ifi_index. -If it is a "virtual interface" (f.e. tunnel), ifi_link -can point to real physical interface (f.e. for bandwidth calculations), -or maybe 0, what means, that real media is unknown (usual -for IPIP tunnels, when route to endpoint is allowed to change) -*/ - -/* Subtype attributes for IFLA_PROTINFO */ -enum -{ -IFLA_INET6_UNSPEC , -IFLA_INET6_FLAGS ,/* link flags */ -IFLA_INET6_CONF ,/* sysctl parameters */ -IFLA_INET6_STATS ,/* statistics */ -IFLA_INET6_MCAST ,/* MC things. What of them? */ -IFLA_INET6_CACHEINFO ,/* time values and max reasm size */ - __IFLA_INET6_MAX -}; - -#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) - -struct ifla_cacheinfo -{ -__u32 max_reasm_len; -__u32 tstamp;/* ipv6InterfaceTable updated timestamp */ -__u32 reachable_time; -__u32 retrans_time; -};/***************************************************************** * Traffic control messages.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
David Miller
maintainerRe: [PATCH 9/9] [NET]: Move netlink interface bits to linux/if.h
From: Stephen Hemminger <[email protected]>
Date: Sat, 05 Aug 2006 22:42:18 -0700
Quoted 13 lines
include/linux/rtnetlink.h struct prefix_cacheinfo · line 616
Quoted 8 lines · Thomas Graf
include/linux/rtnetlink.h +0
-7-/* The struct should be in sync with struct net_device_stats */ -struct rtnl_link_stats -{ -__u32 rx_packets;/* total packets received */ -__u32 tx_packets;/* total packets transmitted */ -__u32 rx_bytes;/* total bytes received */ -__u32 tx_bytes;/* total bytes transmitted */ Make the packets and byte counts
__u64so if/when we extendnet_devicestats to bigger
values, the message format doesn't have to change.
It's an existing ABI that he is just moving from one place to another, we are not at liberty to change it's layout.
We chould create a new one, but that makes no sense until the device layer actually has the means by which to maintain u64 values.
Re: [PATCH 9/9] [NET]: Move netlink interface bits to linux/if.h
Quoted 17 lines · On Fri, 04 Aug 2006 23:23:14 -0700 (PDT) David Miller <[email protected]>…
From: Stephen Hemminger <[email protected]>
Date: Sat, 05 Aug 2006 22:42:18 -0700Quoted 13 lines
include/linux/rtnetlink.h struct prefix_cacheinfo · line 616
Quoted 8 lines · Thomas Graf
include/linux/rtnetlink.h +0
-7-/* The struct should be in sync with struct net_device_stats */ -struct rtnl_link_stats -{ -__u32 rx_packets;/* total packets received */ -__u32 tx_packets;/* total packets transmitted */ -__u32 rx_bytes;/* total bytes received */ -__u32 tx_bytes;/* total bytes transmitted */ Make the packets and byte counts
__u64so if/when we extendnet_devicestats to bigger
values, the message format doesn't have to change.
Quoted 2 lines
It's an existing ABI that he is just moving from one place to another, we are not at liberty to change it's layout.
Yeah that makes sense, I thought it was a new interface.
Signature · 2 lines
Stephen Hemminger <[email protected]> "And in the Packet there writ down that doome"
David Miller
maintainerFrom: Thomas Graf <[email protected]>
Date: Sat, 05 Aug 2006 02:34:52 +0200
Quoted 2 lines
First batch of patches converting existing netlink code to use the new api. Fixing lots of unvalidated accesses to attributes.
Looks very nice, all applied to net-2.6.19, thanks Thomas.
I've also rebased the net-2.6.19 GIT tree.