* @attrs: netlink attributes
  * @_net: network namespace
  * @user_ptr: user pointers
+ * @extack: extended ACK report struct
  */
 struct genl_info {
        u32                     snd_seq;
        struct nlattr **        attrs;
        possible_net_t          _net;
        void *                  user_ptr[2];
+       struct netlink_ext_ack *extack;
 };
 
 static inline struct net *genl_info_net(struct genl_info *info)
        write_pnet(&info->_net, net);
 }
 
+#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG((info)->extack, msg)
+
+static inline int genl_err_attr(struct genl_info *info, int err,
+                               struct nlattr *attr)
+{
+       info->extack->bad_attr = attr;
+
+       return err;
+}
+
 /**
  * struct genl_ops - generic netlink operations
  * @cmd: command identifier
 
 
 static int genl_family_rcv_msg(const struct genl_family *family,
                               struct sk_buff *skb,
-                              struct nlmsghdr *nlh)
+                              struct nlmsghdr *nlh,
+                              struct netlink_ext_ack *extack)
 {
        const struct genl_ops *ops;
        struct net *net = sock_net(skb->sk);
        info.genlhdr = nlmsg_data(nlh);
        info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
        info.attrs = attrbuf;
+       info.extack = extack;
        genl_info_net_set(&info, net);
        memset(&info.user_ptr, 0, sizeof(info.user_ptr));
 
        if (!family->parallel_ops)
                genl_lock();
 
-       err = genl_family_rcv_msg(family, skb, nlh);
+       err = genl_family_rcv_msg(family, skb, nlh, extack);
 
        if (!family->parallel_ops)
                genl_unlock();