Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / include / linux / rtnetlink.h
index fbf366e..df0cdd4 100644 (file)
 
 /* Types of messages */
 
-#define RTM_BASE       0x10
-
-#define        RTM_NEWLINK     (RTM_BASE+0)
-#define        RTM_DELLINK     (RTM_BASE+1)
-#define        RTM_GETLINK     (RTM_BASE+2)
-#define        RTM_SETLINK     (RTM_BASE+3)
-
-#define        RTM_NEWADDR     (RTM_BASE+4)
-#define        RTM_DELADDR     (RTM_BASE+5)
-#define        RTM_GETADDR     (RTM_BASE+6)
-
-#define        RTM_NEWROUTE    (RTM_BASE+8)
-#define        RTM_DELROUTE    (RTM_BASE+9)
-#define        RTM_GETROUTE    (RTM_BASE+10)
-
-#define        RTM_NEWNEIGH    (RTM_BASE+12)
-#define        RTM_DELNEIGH    (RTM_BASE+13)
-#define        RTM_GETNEIGH    (RTM_BASE+14)
-
-#define        RTM_NEWRULE     (RTM_BASE+16)
-#define        RTM_DELRULE     (RTM_BASE+17)
-#define        RTM_GETRULE     (RTM_BASE+18)
-
-#define        RTM_NEWQDISC    (RTM_BASE+20)
-#define        RTM_DELQDISC    (RTM_BASE+21)
-#define        RTM_GETQDISC    (RTM_BASE+22)
-
-#define        RTM_NEWTCLASS   (RTM_BASE+24)
-#define        RTM_DELTCLASS   (RTM_BASE+25)
-#define        RTM_GETTCLASS   (RTM_BASE+26)
-
-#define        RTM_NEWTFILTER  (RTM_BASE+28)
-#define        RTM_DELTFILTER  (RTM_BASE+29)
-#define        RTM_GETTFILTER  (RTM_BASE+30)
-
-#define RTM_NEWPREFIX  (RTM_BASE+36)
-#define RTM_GETPREFIX  (RTM_BASE+38)
-
-#define        RTM_GETMULTICAST (RTM_BASE+42)
-
-#define        RTM_GETANYCAST  (RTM_BASE+46)
+enum {
+       RTM_BASE        = 16,
+#define RTM_BASE       RTM_BASE
+
+       RTM_NEWLINK     = 16,
+#define RTM_NEWLINK    RTM_NEWLINK
+       RTM_DELLINK,
+#define RTM_DELLINK    RTM_DELLINK
+       RTM_GETLINK,
+#define RTM_GETLINK    RTM_GETLINK
+       RTM_SETLINK,
+#define RTM_SETLINK    RTM_SETLINK
+
+       RTM_NEWADDR     = 20,
+#define RTM_NEWADDR    RTM_NEWADDR
+       RTM_DELADDR,
+#define RTM_DELADDR    RTM_DELADDR
+       RTM_GETADDR,
+#define RTM_GETADDR    RTM_GETADDR
+
+       RTM_NEWROUTE    = 24,
+#define RTM_NEWROUTE   RTM_NEWROUTE
+       RTM_DELROUTE,
+#define RTM_DELROUTE   RTM_DELROUTE
+       RTM_GETROUTE,
+#define RTM_GETROUTE   RTM_GETROUTE
+
+       RTM_NEWNEIGH    = 28,
+#define RTM_NEWNEIGH   RTM_NEWNEIGH
+       RTM_DELNEIGH,
+#define RTM_DELNEIGH   RTM_DELNEIGH
+       RTM_GETNEIGH,
+#define RTM_GETNEIGH   RTM_GETNEIGH
+
+       RTM_NEWRULE     = 32,
+#define RTM_NEWRULE    RTM_NEWRULE
+       RTM_DELRULE,
+#define RTM_DELRULE    RTM_DELRULE
+       RTM_GETRULE,
+#define RTM_GETRULE    RTM_GETRULE
+
+       RTM_NEWQDISC    = 36,
+#define RTM_NEWQDISC   RTM_NEWQDISC
+       RTM_DELQDISC,
+#define RTM_DELQDISC   RTM_DELQDISC
+       RTM_GETQDISC,
+#define RTM_GETQDISC   RTM_GETQDISC
+
+       RTM_NEWTCLASS   = 40,
+#define RTM_NEWTCLASS  RTM_NEWTCLASS
+       RTM_DELTCLASS,
+#define RTM_DELTCLASS  RTM_DELTCLASS
+       RTM_GETTCLASS,
+#define RTM_GETTCLASS  RTM_GETTCLASS
+
+       RTM_NEWTFILTER  = 44,
+#define RTM_NEWTFILTER RTM_NEWTFILTER
+       RTM_DELTFILTER,
+#define RTM_DELTFILTER RTM_DELTFILTER
+       RTM_GETTFILTER,
+#define RTM_GETTFILTER RTM_GETTFILTER
+
+       RTM_NEWACTION   = 48,
+#define RTM_NEWACTION   RTM_NEWACTION
+       RTM_DELACTION,
+#define RTM_DELACTION   RTM_DELACTION
+       RTM_GETACTION,
+#define RTM_GETACTION   RTM_GETACTION
+
+       RTM_NEWPREFIX   = 52,
+#define RTM_NEWPREFIX  RTM_NEWPREFIX
+       RTM_GETPREFIX   = 54,
+#define RTM_GETPREFIX  RTM_GETPREFIX
+
+       RTM_GETMULTICAST = 58,
+#define RTM_GETMULTICAST RTM_GETMULTICAST
+
+       RTM_GETANYCAST  = 62,
+#define RTM_GETANYCAST RTM_GETANYCAST
+
+       RTM_NEWNEIGHTBL = 64,
+#define RTM_NEWNEIGHTBL        RTM_NEWNEIGHTBL
+       RTM_GETNEIGHTBL = 66,
+#define RTM_GETNEIGHTBL        RTM_GETNEIGHTBL
+       RTM_SETNEIGHTBL,
+#define RTM_SETNEIGHTBL        RTM_SETNEIGHTBL
+
+       __RTM_MAX,
+#define RTM_MAX                (((__RTM_MAX + 3) & ~3) - 1)
+};
 
-#define        RTM_MAX         (RTM_BASE+47)
+#define RTM_NR_MSGTYPES        (RTM_MAX + 1 - RTM_BASE)
+#define RTM_NR_FAMILIES        (RTM_NR_MSGTYPES >> 2)
+#define RTM_FAM(cmd)   (((cmd) - RTM_BASE) >> 2)
 
 /* 
    Generic structure for encapsulation of optional route information.
@@ -69,7 +120,8 @@ struct rtattr
 
 #define RTA_ALIGNTO    4
 #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
-#define RTA_OK(rta,len) ((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \
+#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
+                        (rta)->rta_len >= sizeof(struct rtattr) && \
                         (rta)->rta_len <= (len))
 #define RTA_NEXT(rta,attrlen)  ((attrlen) -= RTA_ALIGN((rta)->rta_len), \
                                 (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
@@ -118,9 +170,10 @@ enum
        RTN_THROW,              /* Not in this table            */
        RTN_NAT,                /* Translate this address       */
        RTN_XRESOLVE,           /* Use external resolver        */
+       __RTN_MAX
 };
 
-#define RTN_MAX RTN_XRESOLVE
+#define RTN_MAX (__RTN_MAX - 1)
 
 
 /* rtm_protocol */
@@ -146,6 +199,7 @@ enum
 #define RTPROT_BIRD    12      /* BIRD */
 #define RTPROT_DNROUTED        13      /* DECnet routing daemon */
 #define RTPROT_XORP    14      /* XORP */
+#define RTPROT_NTK     15      /* Netsukuku */
 
 /* rtm_scope
 
@@ -183,9 +237,10 @@ enum rt_class_t
 /* User defined values */
        RT_TABLE_DEFAULT=253,
        RT_TABLE_MAIN=254,
-       RT_TABLE_LOCAL=255
+       RT_TABLE_LOCAL=255,
+       __RT_TABLE_MAX
 };
-#define RT_TABLE_MAX RT_TABLE_LOCAL
+#define RT_TABLE_MAX (__RT_TABLE_MAX - 1)
 
 
 
@@ -207,9 +262,11 @@ enum rtattr_type_t
        RTA_FLOW,
        RTA_CACHEINFO,
        RTA_SESSION,
+       RTA_MP_ALGO,
+       __RTA_MAX
 };
 
-#define RTA_MAX RTA_SESSION
+#define RTA_MAX (__RTA_MAX - 1)
 
 #define RTM_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
 #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
@@ -294,17 +351,21 @@ enum
 #define RTAX_INITCWND RTAX_INITCWND
        RTAX_FEATURES,
 #define RTAX_FEATURES RTAX_FEATURES
+       __RTAX_MAX
 };
 
-#define RTAX_MAX RTAX_FEATURES
+#define RTAX_MAX (__RTAX_MAX - 1)
 
 #define RTAX_FEATURE_ECN       0x00000001
 #define RTAX_FEATURE_SACK      0x00000002
 #define RTAX_FEATURE_TIMESTAMP 0x00000004
+#define RTAX_FEATURE_ALLFRAG   0x00000008
 
 struct rta_session
 {
        __u8    proto;
+       __u8    pad1;
+       __u16   pad2;
 
        union {
                struct {
@@ -345,10 +406,11 @@ enum
        IFA_BROADCAST,
        IFA_ANYCAST,
        IFA_CACHEINFO,
-       IFA_MULTICAST
+       IFA_MULTICAST,
+       __IFA_MAX
 };
 
-#define IFA_MAX IFA_CACHEINFO
+#define IFA_MAX (__IFA_MAX - 1)
 
 /* ifa_flags */
 
@@ -399,10 +461,12 @@ enum
        NDA_UNSPEC,
        NDA_DST,
        NDA_LLADDR,
-       NDA_CACHEINFO
+       NDA_CACHEINFO,
+       NDA_PROBES,
+       __NDA_MAX
 };
 
-#define NDA_MAX NDA_CACHEINFO
+#define NDA_MAX (__NDA_MAX - 1)
 
 #define NDA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
 #define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
@@ -439,6 +503,106 @@ struct nda_cacheinfo
        __u32           ndm_refcnt;
 };
 
+
+/*****************************************************************
+ *             Neighbour tables specific messages.
+ *
+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
+ * NLM_F_DUMP flag set. Every neighbour table configuration is
+ * spread over multiple messages to avoid running into message
+ * size limits on systems with many interfaces. The first message
+ * in the sequence transports all not device specific data such as
+ * statistics, configuration, and the default parameter set.
+ * This message is followed by 0..n messages carrying device
+ * specific parameter sets.
+ * Although the ordering should be sufficient, NDTA_NAME can be
+ * used to identify sequences. The initial message can be identified
+ * by checking for NDTA_CONFIG. The device specific messages do
+ * not contain this TLV but have NDTPA_IFINDEX set to the
+ * corresponding interface index.
+ *
+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
+ * otherwise. Device specific parameter sets can be changed by
+ * setting NDTPA_IFINDEX to the interface index of the corresponding
+ * device.
+ ****/
+
+struct ndt_stats
+{
+       __u64           ndts_allocs;
+       __u64           ndts_destroys;
+       __u64           ndts_hash_grows;
+       __u64           ndts_res_failed;
+       __u64           ndts_lookups;
+       __u64           ndts_hits;
+       __u64           ndts_rcv_probes_mcast;
+       __u64           ndts_rcv_probes_ucast;
+       __u64           ndts_periodic_gc_runs;
+       __u64           ndts_forced_gc_runs;
+};
+
+enum {
+       NDTPA_UNSPEC,
+       NDTPA_IFINDEX,                  /* u32, unchangeable */
+       NDTPA_REFCNT,                   /* u32, read-only */
+       NDTPA_REACHABLE_TIME,           /* u64, read-only, msecs */
+       NDTPA_BASE_REACHABLE_TIME,      /* u64, msecs */
+       NDTPA_RETRANS_TIME,             /* u64, msecs */
+       NDTPA_GC_STALETIME,             /* u64, msecs */
+       NDTPA_DELAY_PROBE_TIME,         /* u64, msecs */
+       NDTPA_QUEUE_LEN,                /* u32 */
+       NDTPA_APP_PROBES,               /* u32 */
+       NDTPA_UCAST_PROBES,             /* u32 */
+       NDTPA_MCAST_PROBES,             /* u32 */
+       NDTPA_ANYCAST_DELAY,            /* u64, msecs */
+       NDTPA_PROXY_DELAY,              /* u64, msecs */
+       NDTPA_PROXY_QLEN,               /* u32 */
+       NDTPA_LOCKTIME,                 /* u64, msecs */
+       __NDTPA_MAX
+};
+#define NDTPA_MAX (__NDTPA_MAX - 1)
+
+struct ndtmsg
+{
+       __u8            ndtm_family;
+       __u8            ndtm_pad1;
+       __u16           ndtm_pad2;
+};
+
+struct ndt_config
+{
+       __u16           ndtc_key_len;
+       __u16           ndtc_entry_size;
+       __u32           ndtc_entries;
+       __u32           ndtc_last_flush;        /* delta to now in msecs */
+       __u32           ndtc_last_rand;         /* delta to now in msecs */
+       __u32           ndtc_hash_rnd;
+       __u32           ndtc_hash_mask;
+       __u32           ndtc_hash_chain_gc;
+       __u32           ndtc_proxy_qlen;
+};
+
+enum {
+       NDTA_UNSPEC,
+       NDTA_NAME,                      /* char *, unchangeable */
+       NDTA_THRESH1,                   /* u32 */
+       NDTA_THRESH2,                   /* u32 */
+       NDTA_THRESH3,                   /* u32 */
+       NDTA_CONFIG,                    /* struct ndt_config, read-only */
+       NDTA_PARMS,                     /* nested TLV NDTPA_* */
+       NDTA_STATS,                     /* struct ndt_stats, read-only */
+       NDTA_GC_INTERVAL,               /* u64, msecs */
+       __NDTA_MAX
+};
+#define NDTA_MAX (__NDTA_MAX - 1)
+
+#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
+                    NLMSG_ALIGN(sizeof(struct ndtmsg))))
+#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
+
+
 /****
  *             General form of address family dependent message.
  ****/
@@ -474,10 +638,13 @@ struct ifinfomsg
 struct prefixmsg
 {
        unsigned char   prefix_family;
+       unsigned char   prefix_pad1;
+       unsigned short  prefix_pad2;
        int             prefix_ifindex;
        unsigned char   prefix_type;
        unsigned char   prefix_len;
        unsigned char   prefix_flags;
+       unsigned char   prefix_pad3;
 };
 
 enum 
@@ -485,9 +652,10 @@ enum
        PREFIX_UNSPEC,
        PREFIX_ADDRESS,
        PREFIX_CACHEINFO,
+       __PREFIX_MAX
 };
 
-#define PREFIX_MAX     PREFIX_CACHEINFO
+#define PREFIX_MAX     (__PREFIX_MAX - 1)
 
 struct prefix_cacheinfo
 {
@@ -529,6 +697,17 @@ struct rtnl_link_stats
        __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,
@@ -549,10 +728,19 @@ enum
 #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_PROTINFO
+#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))
@@ -595,8 +783,11 @@ enum
        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;
@@ -605,8 +796,6 @@ struct ifla_cacheinfo
        __u32   retrans_time;
 };
 
-#define IFLA_INET6_MAX IFLA_INET6_CACHEINFO
-
 /*****************************************************************
  *             Traffic control messages.
  ****/
@@ -630,20 +819,18 @@ enum
        TCA_STATS,
        TCA_XSTATS,
        TCA_RATE,
+       TCA_FCNT,
+       TCA_STATS2,
+       __TCA_MAX
 };
 
-#define TCA_MAX TCA_RATE
+#define TCA_MAX (__TCA_MAX - 1)
 
 #define TCA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
-
-/* SUMMARY: maximal rtattr understood by kernel */
-
-#define RTATTR_MAX             RTA_MAX
-
-/* RTnetlink multicast groups */
-
+#ifndef __KERNEL__
+/* RTnetlink multicast groups - backwards compatibility for userspace */
 #define RTMGRP_LINK            1
 #define RTMGRP_NOTIFY          2
 #define RTMGRP_NEIGH           4
@@ -652,6 +839,7 @@ enum
 #define RTMGRP_IPV4_IFADDR     0x10
 #define RTMGRP_IPV4_MROUTE     0x20
 #define RTMGRP_IPV4_ROUTE      0x40
+#define RTMGRP_IPV4_RULE       0x80
 
 #define RTMGRP_IPV6_IFADDR     0x100
 #define RTMGRP_IPV6_MROUTE     0x200
@@ -662,13 +850,69 @@ enum
 #define RTMGRP_DECnet_ROUTE     0x4000
 
 #define RTMGRP_IPV6_PREFIX     0x20000
+#endif
+
+/* RTnetlink multicast groups */
+enum rtnetlink_groups {
+       RTNLGRP_NONE,
+#define RTNLGRP_NONE           RTNLGRP_NONE
+       RTNLGRP_LINK,
+#define RTNLGRP_LINK           RTNLGRP_LINK
+       RTNLGRP_NOTIFY,
+#define RTNLGRP_NOTIFY         RTNLGRP_NOTIFY
+       RTNLGRP_NEIGH,
+#define RTNLGRP_NEIGH          RTNLGRP_NEIGH
+       RTNLGRP_TC,
+#define RTNLGRP_TC             RTNLGRP_TC
+       RTNLGRP_IPV4_IFADDR,
+#define RTNLGRP_IPV4_IFADDR    RTNLGRP_IPV4_IFADDR
+       RTNLGRP_IPV4_MROUTE,
+#define        RTNLGRP_IPV4_MROUTE     RTNLGRP_IPV4_MROUTE
+       RTNLGRP_IPV4_ROUTE,
+#define RTNLGRP_IPV4_ROUTE     RTNLGRP_IPV4_ROUTE
+       RTNLGRP_IPV4_RULE,
+#define RTNLGRP_IPV4_RULE      RTNLGRP_IPV4_RULE
+       RTNLGRP_IPV6_IFADDR,
+#define RTNLGRP_IPV6_IFADDR    RTNLGRP_IPV6_IFADDR
+       RTNLGRP_IPV6_MROUTE,
+#define RTNLGRP_IPV6_MROUTE    RTNLGRP_IPV6_MROUTE
+       RTNLGRP_IPV6_ROUTE,
+#define RTNLGRP_IPV6_ROUTE     RTNLGRP_IPV6_ROUTE
+       RTNLGRP_IPV6_IFINFO,
+#define RTNLGRP_IPV6_IFINFO    RTNLGRP_IPV6_IFINFO
+       RTNLGRP_DECnet_IFADDR,
+#define RTNLGRP_DECnet_IFADDR  RTNLGRP_DECnet_IFADDR
+       RTNLGRP_NOP2,
+       RTNLGRP_DECnet_ROUTE,
+#define RTNLGRP_DECnet_ROUTE   RTNLGRP_DECnet_ROUTE
+       RTNLGRP_NOP3,
+       RTNLGRP_NOP4,
+       RTNLGRP_IPV6_PREFIX,
+#define RTNLGRP_IPV6_PREFIX    RTNLGRP_IPV6_PREFIX
+       __RTNLGRP_MAX
+};
+#define RTNLGRP_MAX    (__RTNLGRP_MAX - 1)
+
+/* TC action piece */
+struct tcamsg
+{
+       unsigned char   tca_family;
+       unsigned char   tca__pad1;
+       unsigned short  tca__pad2;
+};
+#define TA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg))))
+#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg))
+#define TCA_ACT_TAB 1 /* attr type must be >=1 */      
+#define TCAA_MAX 1
 
 /* End of information exported to user level */
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <linux/mutex.h>
 
+extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
 static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
 {
        int len = strlen(str) + 1;
@@ -677,6 +921,9 @@ static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
 
 extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
 
+#define rtattr_parse_nested(tb, max, rta) \
+       rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
+
 extern struct sock *rtnl;
 
 struct rtnetlink_link
@@ -686,7 +933,6 @@ struct rtnetlink_link
 };
 
 extern struct rtnetlink_link * rtnetlink_links[NPROTO];
-extern int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb);
 extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
 extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
 
@@ -697,6 +943,85 @@ extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const voi
                 goto rtattr_failure; \
        __rta_fill(skb, attrtype, attrlen, data); }) 
 
+#define RTA_APPEND(skb, attrlen, data) \
+({     if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \
+               goto rtattr_failure; \
+       memcpy(skb_put(skb, attrlen), data, attrlen); })
+
+#define RTA_PUT_NOHDR(skb, attrlen, data) \
+({     RTA_APPEND(skb, RTA_ALIGN(attrlen), data); \
+       memset(skb->tail - (RTA_ALIGN(attrlen) - attrlen), 0, \
+              RTA_ALIGN(attrlen) - attrlen); })
+
+#define RTA_PUT_U8(skb, attrtype, value) \
+({     u8 _tmp = (value); \
+       RTA_PUT(skb, attrtype, sizeof(u8), &_tmp); })
+
+#define RTA_PUT_U16(skb, attrtype, value) \
+({     u16 _tmp = (value); \
+       RTA_PUT(skb, attrtype, sizeof(u16), &_tmp); })
+
+#define RTA_PUT_U32(skb, attrtype, value) \
+({     u32 _tmp = (value); \
+       RTA_PUT(skb, attrtype, sizeof(u32), &_tmp); })
+
+#define RTA_PUT_U64(skb, attrtype, value) \
+({     u64 _tmp = (value); \
+       RTA_PUT(skb, attrtype, sizeof(u64), &_tmp); })
+
+#define RTA_PUT_SECS(skb, attrtype, value) \
+       RTA_PUT_U64(skb, attrtype, (value) / HZ)
+
+#define RTA_PUT_MSECS(skb, attrtype, value) \
+       RTA_PUT_U64(skb, attrtype, jiffies_to_msecs(value))
+
+#define RTA_PUT_STRING(skb, attrtype, value) \
+       RTA_PUT(skb, attrtype, strlen(value) + 1, value)
+
+#define RTA_PUT_FLAG(skb, attrtype) \
+       RTA_PUT(skb, attrtype, 0, NULL);
+
+#define RTA_NEST(skb, type) \
+({     struct rtattr *__start = (struct rtattr *) (skb)->tail; \
+       RTA_PUT(skb, type, 0, NULL); \
+       __start;  })
+
+#define RTA_NEST_END(skb, start) \
+({     (start)->rta_len = ((skb)->tail - (unsigned char *) (start)); \
+       (skb)->len; })
+
+#define RTA_NEST_CANCEL(skb, start) \
+({     if (start) \
+               skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
+       -1; })
+
+#define RTA_GET_U8(rta) \
+({     if (!rta || RTA_PAYLOAD(rta) < sizeof(u8)) \
+               goto rtattr_failure; \
+       *(u8 *) RTA_DATA(rta); })
+
+#define RTA_GET_U16(rta) \
+({     if (!rta || RTA_PAYLOAD(rta) < sizeof(u16)) \
+               goto rtattr_failure; \
+       *(u16 *) RTA_DATA(rta); })
+
+#define RTA_GET_U32(rta) \
+({     if (!rta || RTA_PAYLOAD(rta) < sizeof(u32)) \
+               goto rtattr_failure; \
+       *(u32 *) RTA_DATA(rta); })
+
+#define RTA_GET_U64(rta) \
+({     u64 _tmp; \
+       if (!rta || RTA_PAYLOAD(rta) < sizeof(u64)) \
+               goto rtattr_failure; \
+       memcpy(&_tmp, RTA_DATA(rta), sizeof(_tmp)); \
+       _tmp; })
+
+#define RTA_GET_FLAG(rta) (!!(rta))
+
+#define RTA_GET_SECS(rta) ((unsigned long) RTA_GET_U64(rta) * HZ)
+#define RTA_GET_MSECS(rta) (msecs_to_jiffies((unsigned long) RTA_GET_U64(rta)))
+               
 static inline struct rtattr *
 __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
 {
@@ -706,6 +1031,7 @@ __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
        rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size));
        rta->rta_type = attrtype;
        rta->rta_len = size;
+       memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size);
        return rta;
 }
 
@@ -716,27 +1042,17 @@ __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
 
 extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
 
-extern struct semaphore rtnl_sem;
-
-#define rtnl_exlock()          do { } while(0)
-#define rtnl_exunlock()                do { } while(0)
-#define rtnl_exlock_nowait()   (0)
-
-#define rtnl_shlock()          down(&rtnl_sem)
-#define rtnl_shlock_nowait()   down_trylock(&rtnl_sem)
-
-#define rtnl_shunlock()        do { up(&rtnl_sem); \
-                            if (rtnl && rtnl->sk_receive_queue.qlen) \
-                                    rtnl->sk_data_ready(rtnl, 0); \
-                       } while(0)
-
+/* RTNL is used as a global lock for all changes to network configuration  */
 extern void rtnl_lock(void);
 extern void rtnl_unlock(void);
+extern int rtnl_trylock(void);
+
 extern void rtnetlink_init(void);
+extern void __rtnl_unlock(void);
 
 #define ASSERT_RTNL() do { \
-       if (unlikely(down_trylock(&rtnl_sem) == 0)) { \
-               up(&rtnl_sem); \
+       if (unlikely(rtnl_trylock())) { \
+               rtnl_unlock(); \
                printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
                       __FILE__,  __LINE__); \
                dump_stack(); \