+static inline int get_ports(const struct sk_buff *skb, int offset,
+ u16 ports[2])
+{
+ union {
+ struct tcphdr th;
+ struct udphdr uh;
+ sctp_sctphdr_t sctph;
+ } hdr_u, *ptr_u;
+
+ /* Must not be a fragment. */
+ if (offset)
+ return 1;
+
+ /* Must be big enough to read ports (both UDP and TCP have
+ them at the start). */
+ ptr_u = skb_header_pointer(skb, skb->nh.iph->ihl*4, 8, &hdr_u);
+ if (!ptr_u)
+ return 1;
+
+ switch (skb->nh.iph->protocol) {
+ case IPPROTO_TCP:
+ ports[0] = ptr_u->th.source;
+ ports[1] = ptr_u->th.dest;
+ break;
+ case IPPROTO_UDP:
+ ports[0] = ptr_u->uh.source;
+ ports[1] = ptr_u->uh.dest;
+ break;
+ case IPPROTO_SCTP:
+ ports[0] = ptr_u->sctph.source;
+ ports[1] = ptr_u->sctph.dest;
+ break;
+ default:
+ /* all other protocols don't supprot per-port hash
+ * buckets */
+ ports[0] = ports[1] = 0;
+ break;
+ }
+
+ return 0;
+}
+
+