From 080fb7363513df1308b13ecc658bbc5e5ca5df37 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Wed, 2 Feb 2011 20:29:44 +0100 Subject: [PATCH] netfilter: ipset: send error message manually When a message carries multiple commands and one of them triggers an error, we have to report to the userspace which one was that. The line number of the command plays this role and there's an attribute reserved in the header part of the message to be filled out with the error line number. In order not to modify the original message received from the userspace, we construct a new, complete netlink error message and modifies the attribute there, then send it. Netlink is notified not to send its ACK/error message. Signed-off-by: Jozsef Kadlecsik nlmsg_seq, NLMSG_ERROR, payload, 0); + errmsg = nlmsg_data(rep); + errmsg->error = ret; + memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); + cmdattr = (void *)&errmsg->msg + min_len; + nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr, nlh->nlmsg_len - min_len, ip_set_adt_policy); @@ -1131,6 +1144,10 @@ call_ad(struct sk_buff *skb, struct ip_set *set, errline = nla_data(cda[IPSET_ATTR_LINENO]); *errline = lineno; + + netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); + /* Signal netlink not to send its ACK/errmsg. */ + return -EINTR; } return ret; @@ -1169,7 +1186,8 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb, attr[IPSET_ATTR_DATA], set->type->adt_policy)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(skb, set, tb, IPSET_ADD, flags, use_lineno); + ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags, + use_lineno); } else { int nla_rem; @@ -1180,7 +1198,7 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb, nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, set->type->adt_policy)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(skb, set, tb, IPSET_ADD, + ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags, use_lineno); if (ret < 0) return ret; @@ -1222,7 +1240,8 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb, attr[IPSET_ATTR_DATA], set->type->adt_policy)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(skb, set, tb, IPSET_DEL, flags, use_lineno); + ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags, + use_lineno); } else { int nla_rem; @@ -1233,7 +1252,7 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb, nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, set->type->adt_policy)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(skb, set, tb, IPSET_DEL, + ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags, use_lineno); if (ret < 0) return ret; -- 1.7.0.4