fix connection marking

this commit fixes 3 issues:

1. the mark was being pulled from the skb in the post_routing_hook
   regardless of its value, which could be zero.

2. the event parameter of the conntrack event callback was being
   incorrectly tested for the IPCT_MARK flag. the following function was
   used as an example for how to properly test the flag:
   netfilter/nf_conntrack_netlink.c:ctnetlink_conntrack_event.

3. the mark wasn't being pulled from the nfct object during a
   conntrack event, which resulted in overwriting a connection's
   mark with garbage.  now that I think about it, this probably
   explains the presence of the mark manipulation code in the
   post_routing_hook (issue resolution #1).

Change-Id: I2404bfc4142f79d68bb93400b85cdb2c9f7bc5a8
Signed-off-by: Nicolas Costa <ncosta@codeaurora.org>
diff --git a/fast-classifier/fast-classifier.c b/fast-classifier/fast-classifier.c
index 91db303..968567e 100644
--- a/fast-classifier/fast-classifier.c
+++ b/fast-classifier/fast-classifier.c
@@ -558,10 +558,14 @@
 		    p_sic->dest_port == sic.dest_port &&
 		    p_sic->src_ip == sic.src_ip &&
 		    p_sic->dest_ip == sic.dest_ip ) {
-			if (skb->mark) {
+			/* is this really necessary?  shouldn't the conntrack
+			   callback be sufficient for tracking the conmark?
+			   regardless, don't overwrite the sic mark if the
+			   skb's mark is zero */
+			if (skb->mark != 0) {
 				DEBUG_TRACE("UPDATING MARK %x\n", skb->mark);
+				p_sic->mark = skb->mark;
 			}
-			p_sic->mark = skb->mark;
 
 
 			conn->hits++;
@@ -795,29 +799,6 @@
 	unsigned long flags;
 	struct fast_classifier_tuple fc_msg;
 
-	if (events & IPCT_MARK) {
-		struct sfe_ipv4_mark mark;
-		orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-
-		mark.protocol = (int32_t)orig_tuple.dst.protonum;
-		mark.src_ip = (__be32)orig_tuple.src.u3.ip;
-		mark.dest_ip = (__be32)orig_tuple.dst.u3.ip;
-		switch (mark.protocol) {
-		case IPPROTO_TCP:
-			mark.src_port = orig_tuple.src.u.tcp.port;
-			mark.dest_port = orig_tuple.dst.u.tcp.port;
-			break;
-		case IPPROTO_UDP:
-			mark.src_port = orig_tuple.src.u.udp.port;
-			mark.dest_port = orig_tuple.dst.u.udp.port;
-			break;
-		default:
-			break;
-		}
-
-		sfe_ipv4_mark_rule(&mark);
-	}
-
 	/*
 	 * If we don't have a conntrack entry then we're done.
 	 */
@@ -843,6 +824,33 @@
 	}
 
 	/*
+	 * Check for an updated mark
+	 */
+	if ((events & (1 << IPCT_MARK)) && (ct->mark != 0)) {
+		struct sfe_ipv4_mark mark;
+		orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+
+		mark.protocol = (int32_t)orig_tuple.dst.protonum;
+		mark.src_ip = (__be32)orig_tuple.src.u3.ip;
+		mark.dest_ip = (__be32)orig_tuple.dst.u3.ip;
+		switch (mark.protocol) {
+		case IPPROTO_TCP:
+			mark.src_port = orig_tuple.src.u.tcp.port;
+			mark.dest_port = orig_tuple.dst.u.tcp.port;
+			break;
+		case IPPROTO_UDP:
+			mark.src_port = orig_tuple.src.u.udp.port;
+			mark.dest_port = orig_tuple.dst.u.udp.port;
+			break;
+		default:
+			break;
+		}
+
+		mark.mark = ct->mark;
+		sfe_ipv4_mark_rule(&mark);
+	}
+
+	/*
 	 * We're only interested in destroy events at this point
 	 */
 	if (unlikely(!(events & (1 << IPCT_DESTROY)))) {