|
|
@@ -1419,6 +1419,24 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+static void
|
|
|
+__ctnetlink_change_status(struct nf_conn *ct, unsigned long on,
|
|
|
+ unsigned long off)
|
|
|
+{
|
|
|
+ unsigned int bit;
|
|
|
+
|
|
|
+ /* Ignore these unchangable bits */
|
|
|
+ on &= ~IPS_UNCHANGEABLE_MASK;
|
|
|
+ off &= ~IPS_UNCHANGEABLE_MASK;
|
|
|
+
|
|
|
+ for (bit = 0; bit < __IPS_MAX_BIT; bit++) {
|
|
|
+ if (on & (1 << bit))
|
|
|
+ set_bit(bit, &ct->status);
|
|
|
+ else if (off & (1 << bit))
|
|
|
+ clear_bit(bit, &ct->status);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
|
|
|
{
|
|
|
@@ -1438,10 +1456,7 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
|
|
|
/* ASSURED bit can only be set */
|
|
|
return -EBUSY;
|
|
|
|
|
|
- /* Be careful here, modifying NAT bits can screw up things,
|
|
|
- * so don't let users modify them directly if they don't pass
|
|
|
- * nf_nat_range. */
|
|
|
- ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
|
|
|
+ __ctnetlink_change_status(ct, status, 0);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -1628,7 +1643,7 @@ ctnetlink_change_seq_adj(struct nf_conn *ct,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- ct->status |= IPS_SEQ_ADJUST;
|
|
|
+ set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
|
|
|
}
|
|
|
|
|
|
if (cda[CTA_SEQ_ADJ_REPLY]) {
|
|
|
@@ -1637,7 +1652,7 @@ ctnetlink_change_seq_adj(struct nf_conn *ct,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- ct->status |= IPS_SEQ_ADJUST;
|
|
|
+ set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
@@ -2289,10 +2304,10 @@ ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
|
|
|
/* This check is less strict than ctnetlink_change_status()
|
|
|
* because callers often flip IPS_EXPECTED bits when sending
|
|
|
* an NFQA_CT attribute to the kernel. So ignore the
|
|
|
- * unchangeable bits but do not error out.
|
|
|
+ * unchangeable bits but do not error out. Also user programs
|
|
|
+ * are allowed to clear the bits that they are allowed to change.
|
|
|
*/
|
|
|
- ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
|
|
|
- (ct->status & IPS_UNCHANGEABLE_MASK);
|
|
|
+ __ctnetlink_change_status(ct, status, ~status);
|
|
|
return 0;
|
|
|
}
|
|
|
|