1: /*************************************************************************
2: * (C) 2022 CloudSigma AG - Sofia/Bulgaria
3: * by Michael Pounov <misho@elwix.org>
4: **************************************************************************/
5: #include "fwsync.h"
6:
7:
8: #ifndef IPFIREWALL_JENKINSHASH
9: __inline uint32_t
10: fwsync_hash_packet(const struct ipfw_flow_id *id)
11: {
12: uint32_t i;
13:
14: #ifdef INET6
15: if (IS_IP6_FLOW_ID(id))
16: i = ntohl((id->dst_ip6.__u6_addr.__u6_addr32[2]) ^
17: (id->dst_ip6.__u6_addr.__u6_addr32[3]) ^
18: (id->src_ip6.__u6_addr.__u6_addr32[2]) ^
19: (id->src_ip6.__u6_addr.__u6_addr32[3]));
20: else
21: #endif /* INET6 */
22: i = (id->dst_ip) ^ (id->src_ip);
23: i ^= (id->dst_port) ^ (id->src_port);
24: return (i);
25: }
26:
27: __inline uint32_t
28: fwsync_hash_parent(const struct ipfw_flow_id *id, const void *rule)
29: {
30:
31: return (fwsync_hash_packet(id) ^ ((uintptr_t)rule));
32: }
33:
34: #else /* IPFIREWALL_JENKINSHASH */
35:
36: VNET_DEFINE_STATIC(uint32_t, dyn_hashseed);
37: #define V_dyn_hashseed VNET(dyn_hashseed)
38:
39: static __inline int
40: addrcmp4(const struct ipfw_flow_id *id)
41: {
42:
43: if (id->src_ip < id->dst_ip)
44: return (0);
45: if (id->src_ip > id->dst_ip)
46: return (1);
47: if (id->src_port <= id->dst_port)
48: return (0);
49: return (1);
50: }
51:
52: #ifdef INET6
53: static __inline int
54: addrcmp6(const struct ipfw_flow_id *id)
55: {
56: int ret;
57:
58: ret = memcmp(&id->src_ip6, &id->dst_ip6, sizeof(struct in6_addr));
59: if (ret < 0)
60: return (0);
61: if (ret > 0)
62: return (1);
63: if (id->src_port <= id->dst_port)
64: return (0);
65: return (1);
66: }
67:
68: __inline uint32_t
69: fwsync_hash_packet6(const struct ipfw_flow_id *id)
70: {
71: struct tuple6 {
72: struct in6_addr addr[2];
73: uint16_t port[2];
74: } t6;
75:
76: if (addrcmp6(id) == 0) {
77: t6.addr[0] = id->src_ip6;
78: t6.addr[1] = id->dst_ip6;
79: t6.port[0] = id->src_port;
80: t6.port[1] = id->dst_port;
81: } else {
82: t6.addr[0] = id->dst_ip6;
83: t6.addr[1] = id->src_ip6;
84: t6.port[0] = id->dst_port;
85: t6.port[1] = id->src_port;
86: }
87: return (jenkins_hash32((const uint32_t *)&t6,
88: sizeof(t6) / sizeof(uint32_t), V_dyn_hashseed));
89: }
90: #endif
91:
92: __inline uint32_t
93: fwsync_hash_packet(const struct ipfw_flow_id *id)
94: {
95: struct tuple4 {
96: in_addr_t addr[2];
97: uint16_t port[2];
98: } t4;
99:
100: if (IS_IP4_FLOW_ID(id)) {
101: /* All fields are in host byte order */
102: if (addrcmp4(id) == 0) {
103: t4.addr[0] = id->src_ip;
104: t4.addr[1] = id->dst_ip;
105: t4.port[0] = id->src_port;
106: t4.port[1] = id->dst_port;
107: } else {
108: t4.addr[0] = id->dst_ip;
109: t4.addr[1] = id->src_ip;
110: t4.port[0] = id->dst_port;
111: t4.port[1] = id->src_port;
112: }
113: return (jenkins_hash32((const uint32_t *)&t4,
114: sizeof(t4) / sizeof(uint32_t), V_dyn_hashseed));
115: } else
116: #ifdef INET6
117: if (IS_IP6_FLOW_ID(id))
118: return (fwsync_hash_packet6(id));
119: #endif
120: return (0);
121: }
122:
123: __inline uint32_t
124: fwsync_hash_parent(const struct ipfw_flow_id *id, const void *rule)
125: {
126:
127: return (jenkins_hash32((const uint32_t *)&rule,
128: sizeof(rule) / sizeof(uint32_t), fwsync_hash_packet(id)));
129: }
130: #endif /* IPFIREWALL_JENKINSHASH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>