aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/ipset/ip_set_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter/ipset/ip_set_core.c')
-rw-r--r--net/netfilter/ipset/ip_set_core.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index ae0f8b59510..8b1a54c1e40 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1098,7 +1098,7 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
1098}; 1098};
1099 1099
1100static int 1100static int
1101call_ad(struct sk_buff *skb, struct ip_set *set, 1101call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
1102 struct nlattr *tb[], enum ipset_adt adt, 1102 struct nlattr *tb[], enum ipset_adt adt,
1103 u32 flags, bool use_lineno) 1103 u32 flags, bool use_lineno)
1104{ 1104{
@@ -1118,12 +1118,25 @@ call_ad(struct sk_buff *skb, struct ip_set *set,
1118 return 0; 1118 return 0;
1119 if (lineno && use_lineno) { 1119 if (lineno && use_lineno) {
1120 /* Error in restore/batch mode: send back lineno */ 1120 /* Error in restore/batch mode: send back lineno */
1121 struct nlmsghdr *nlh = nlmsg_hdr(skb); 1121 struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
1122 struct sk_buff *skb2;
1123 struct nlmsgerr *errmsg;
1124 size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
1122 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); 1125 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
1123 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1]; 1126 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
1124 struct nlattr *cmdattr = (void *)nlh + min_len; 1127 struct nlattr *cmdattr;
1125 u32 *errline; 1128 u32 *errline;
1126 1129
1130 skb2 = nlmsg_new(payload, GFP_KERNEL);
1131 if (skb2 == NULL)
1132 return -ENOMEM;
1133 rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid,
1134 nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
1135 errmsg = nlmsg_data(rep);
1136 errmsg->error = ret;
1137 memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
1138 cmdattr = (void *)&errmsg->msg + min_len;
1139
1127 nla_parse(cda, IPSET_ATTR_CMD_MAX, 1140 nla_parse(cda, IPSET_ATTR_CMD_MAX,
1128 cmdattr, nlh->nlmsg_len - min_len, 1141 cmdattr, nlh->nlmsg_len - min_len,
1129 ip_set_adt_policy); 1142 ip_set_adt_policy);
@@ -1131,6 +1144,10 @@ call_ad(struct sk_buff *skb, struct ip_set *set,
1131 errline = nla_data(cda[IPSET_ATTR_LINENO]); 1144 errline = nla_data(cda[IPSET_ATTR_LINENO]);
1132 1145
1133 *errline = lineno; 1146 *errline = lineno;
1147
1148 netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1149 /* Signal netlink not to send its ACK/errmsg. */
1150 return -EINTR;
1134 } 1151 }
1135 1152
1136 return ret; 1153 return ret;
@@ -1169,7 +1186,8 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
1169 attr[IPSET_ATTR_DATA], 1186 attr[IPSET_ATTR_DATA],
1170 set->type->adt_policy)) 1187 set->type->adt_policy))
1171 return -IPSET_ERR_PROTOCOL; 1188 return -IPSET_ERR_PROTOCOL;
1172 ret = call_ad(skb, set, tb, IPSET_ADD, flags, use_lineno); 1189 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags,
1190 use_lineno);
1173 } else { 1191 } else {
1174 int nla_rem; 1192 int nla_rem;
1175 1193
@@ -1180,7 +1198,7 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
1180 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, 1198 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1181 set->type->adt_policy)) 1199 set->type->adt_policy))
1182 return -IPSET_ERR_PROTOCOL; 1200 return -IPSET_ERR_PROTOCOL;
1183 ret = call_ad(skb, set, tb, IPSET_ADD, 1201 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
1184 flags, use_lineno); 1202 flags, use_lineno);
1185 if (ret < 0) 1203 if (ret < 0)
1186 return ret; 1204 return ret;
@@ -1222,7 +1240,8 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
1222 attr[IPSET_ATTR_DATA], 1240 attr[IPSET_ATTR_DATA],
1223 set->type->adt_policy)) 1241 set->type->adt_policy))
1224 return -IPSET_ERR_PROTOCOL; 1242 return -IPSET_ERR_PROTOCOL;
1225 ret = call_ad(skb, set, tb, IPSET_DEL, flags, use_lineno); 1243 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags,
1244 use_lineno);
1226 } else { 1245 } else {
1227 int nla_rem; 1246 int nla_rem;
1228 1247
@@ -1233,7 +1252,7 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
1233 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, 1252 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1234 set->type->adt_policy)) 1253 set->type->adt_policy))
1235 return -IPSET_ERR_PROTOCOL; 1254 return -IPSET_ERR_PROTOCOL;
1236 ret = call_ad(skb, set, tb, IPSET_DEL, 1255 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
1237 flags, use_lineno); 1256 flags, use_lineno);
1238 if (ret < 0) 1257 if (ret < 0)
1239 return ret; 1258 return ret;