aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/ipset
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2011-02-02 17:56:00 -0500
committerPatrick McHardy <kaber@trash.net>2011-02-02 17:56:00 -0500
commit5f52bc3cdd1bb2e12e61639df19d9dcd530c4568 (patch)
treeb4a24cd688e4e87084975d3d6cd338fefe3581b2 /net/netfilter/ipset
parent724bab476bcac9f7d0b5204cb06e346216d42166 (diff)
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 <kadlec@blackhole.kfki.hu Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/netfilter/ipset')
-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;