@@ -1222,6 +1222,8 @@ struct net_device_ops {
netdev_features_t features);
int (*ndo_neigh_construct)(struct neighbour *n);
void (*ndo_neigh_destroy)(struct neighbour *n);
+ int (*ndo_neigh_fill_info)(struct sk_buff *skb,
+ struct neighbour *n);
int (*ndo_fdb_add)(struct ndmsg *ndm,
struct nlattr *tb[],
@@ -1704,6 +1706,7 @@ struct net_device {
unsigned char addr_assign_type;
unsigned char addr_len;
unsigned short neigh_priv_len;
+ unsigned short neigh_priv_nlmsg_len;
unsigned short dev_id;
unsigned short dev_port;
spinlock_t addr_list_lock;
@@ -15,6 +15,13 @@ struct ndmsg {
};
enum {
+ NDA_6LOWPAN_802154_SHORT_ADDR,
+ __NDA_6LOWPAN_MAX
+};
+
+#define NDA_6LOWPAN_MAX (__NDA_6LOWPAN_MAX - 1)
+
+enum {
NDA_UNSPEC,
NDA_DST,
NDA_LLADDR,
@@ -26,6 +33,7 @@ enum {
NDA_IFINDEX,
NDA_MASTER,
NDA_LINK_NETNSID,
+ NDA_PRIVATE,
__NDA_MAX
};
@@ -2153,6 +2153,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
unsigned long now = jiffies;
struct nda_cacheinfo ci;
struct nlmsghdr *nlh;
+ struct nlattr *nest;
struct ndmsg *ndm;
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
@@ -2182,6 +2183,17 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
}
}
+ if (neigh->dev->netdev_ops->ndo_neigh_fill_info) {
+ nest = nla_nest_start(skb, NDA_PRIVATE);
+ if (nest == NULL)
+ return -ENOBUFS;
+
+ if (neigh->dev->netdev_ops->ndo_neigh_fill_info(skb, neigh))
+ goto nla_put_failure;
+
+ nla_nest_end(skb, nest);
+ }
+
ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
@@ -2824,13 +2836,14 @@ static const struct file_operations neigh_stat_seq_fops = {
#endif /* CONFIG_PROC_FS */
-static inline size_t neigh_nlmsg_size(void)
+static inline size_t neigh_nlmsg_size(const struct net_device *dev)
{
return NLMSG_ALIGN(sizeof(struct ndmsg))
+ nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
+ nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
+ nla_total_size(sizeof(struct nda_cacheinfo))
- + nla_total_size(4); /* NDA_PROBES */
+ + nla_total_size(4) /* NDA_PROBES */
+ + nla_total_size(dev->neigh_priv_nlmsg_len);
}
static void __neigh_notify(struct neighbour *n, int type, int flags)
@@ -2839,7 +2852,7 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
struct sk_buff *skb;
int err = -ENOBUFS;
- skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
+ skb = nlmsg_new(neigh_nlmsg_size(n->dev), GFP_ATOMIC);
if (skb == NULL)
goto errout;