1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.netlink;
18 
19 import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
20 import static android.net.netlink.NetlinkConstants.NFNL_SUBSYS_CTNETLINK;
21 
22 import static org.junit.Assert.assertArrayEquals;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assume.assumeTrue;
28 
29 import android.system.OsConstants;
30 
31 import androidx.test.filters.SmallTest;
32 import androidx.test.runner.AndroidJUnit4;
33 
34 import libcore.util.HexEncoding;
35 
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 
39 import java.net.Inet4Address;
40 import java.net.InetAddress;
41 import java.nio.ByteBuffer;
42 import java.nio.ByteOrder;
43 import java.util.Arrays;
44 
45 @RunWith(AndroidJUnit4.class)
46 @SmallTest
47 public class ConntrackMessageTest {
48     private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
49 
makeCtType(short msgType)50     private short makeCtType(short msgType) {
51         return (short) (NFNL_SUBSYS_CTNETLINK << 8 | (byte) msgType);
52     }
53 
54     // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
55     public static final String CT_V4UPDATE_TCP_HEX =
56             // struct nlmsghdr
57             "50000000" +      // length = 80
58             "0001" +          // type = (1 << 8) | 0
59             "0501" +          // flags
60             "01000000" +      // seqno = 1
61             "00000000" +      // pid = 0
62             // struct nfgenmsg
63             "02" +            // nfgen_family  = AF_INET
64             "00" +            // version = NFNETLINK_V0
65             "0000" +          // res_id
66             // struct nlattr
67             "3400" +          // nla_len = 52
68             "0180" +          // nla_type = nested CTA_TUPLE_ORIG
69                 // struct nlattr
70                 "1400" +      // nla_len = 20
71                 "0180" +      // nla_type = nested CTA_TUPLE_IP
72                     "0800 0100 C0A82BD1" +  // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
73                     "0800 0200 17D30D1A" +  // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
74                 // struct nlattr
75                 "1C00" +      // nla_len = 28
76                 "0280" +      // nla_type = nested CTA_TUPLE_PROTO
77                     "0500 0100 06 000000" +  // nla_type=CTA_PROTO_NUM, proto=6
78                     "0600 0200 AD2D 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
79                     "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
80             // struct nlattr
81             "0800" +          // nla_len = 8
82             "0700" +          // nla_type = CTA_TIMEOUT
83             "00069780";       // nla_value = 432000 (big endian)
84     public static final byte[] CT_V4UPDATE_TCP_BYTES =
85             HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
86 
makeIPv4TimeoutUpdateRequestTcp()87     private byte[] makeIPv4TimeoutUpdateRequestTcp() throws Exception {
88         return ConntrackMessage.newIPv4TimeoutUpdateRequest(
89                 OsConstants.IPPROTO_TCP,
90                 (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
91                 (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
92                 432000);
93     }
94 
95     // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
96     public static final String CT_V4UPDATE_UDP_HEX =
97             // struct nlmsghdr
98             "50000000" +      // length = 80
99             "0001" +          // type = (1 << 8) | 0
100             "0501" +          // flags
101             "01000000" +      // seqno = 1
102             "00000000" +      // pid = 0
103             // struct nfgenmsg
104             "02" +            // nfgen_family  = AF_INET
105             "00" +            // version = NFNETLINK_V0
106             "0000" +          // res_id
107             // struct nlattr
108             "3400" +          // nla_len = 52
109             "0180" +          // nla_type = nested CTA_TUPLE_ORIG
110                 // struct nlattr
111                 "1400" +      // nla_len = 20
112                 "0180" +      // nla_type = nested CTA_TUPLE_IP
113                     "0800 0100 6460A792" +  // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
114                     "0800 0200 D83AC50A" +  // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
115                 // struct nlattr
116                 "1C00" +      // nla_len = 28
117                 "0280" +      // nla_type = nested CTA_TUPLE_PROTO
118                     "0500 0100 11 000000" +  // nla_type=CTA_PROTO_NUM, proto=17
119                     "0600 0200 90CD 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
120                     "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
121             // struct nlattr
122             "0800" +          // nla_len = 8
123             "0700" +          // nla_type = CTA_TIMEOUT
124             "000000B4";       // nla_value = 180 (big endian)
125     public static final byte[] CT_V4UPDATE_UDP_BYTES =
126             HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
127 
makeIPv4TimeoutUpdateRequestUdp()128     private byte[] makeIPv4TimeoutUpdateRequestUdp() throws Exception {
129         return ConntrackMessage.newIPv4TimeoutUpdateRequest(
130                 OsConstants.IPPROTO_UDP,
131                 (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
132                 (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
133                 180);
134     }
135 
136     @Test
testConntrackMakeIPv4TcpTimeoutUpdate()137     public void testConntrackMakeIPv4TcpTimeoutUpdate() throws Exception {
138         assumeTrue(USING_LE);
139 
140         final byte[] tcp = makeIPv4TimeoutUpdateRequestTcp();
141         assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
142     }
143 
144     @Test
testConntrackParseIPv4TcpTimeoutUpdate()145     public void testConntrackParseIPv4TcpTimeoutUpdate() throws Exception {
146         assumeTrue(USING_LE);
147 
148         final byte[] tcp = makeIPv4TimeoutUpdateRequestTcp();
149         final ByteBuffer byteBuffer = ByteBuffer.wrap(tcp);
150         byteBuffer.order(ByteOrder.nativeOrder());
151         final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
152         assertNotNull(msg);
153         assertTrue(msg instanceof ConntrackMessage);
154         final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
155 
156         final StructNlMsgHdr hdr = conntrackMessage.getHeader();
157         assertNotNull(hdr);
158         assertEquals(80, hdr.nlmsg_len);
159         assertEquals(makeCtType(IPCTNL_MSG_CT_NEW), hdr.nlmsg_type);
160         assertEquals((short) (StructNlMsgHdr.NLM_F_REPLACE | StructNlMsgHdr.NLM_F_REQUEST
161                 | StructNlMsgHdr.NLM_F_ACK), hdr.nlmsg_flags);
162         assertEquals(1, hdr.nlmsg_seq);
163         assertEquals(0, hdr.nlmsg_pid);
164 
165         final StructNfGenMsg nfmsgHdr = conntrackMessage.nfGenMsg;
166         assertNotNull(nfmsgHdr);
167         assertEquals((byte) OsConstants.AF_INET, nfmsgHdr.nfgen_family);
168         assertEquals((byte) StructNfGenMsg.NFNETLINK_V0, nfmsgHdr.version);
169         assertEquals((short) 0, nfmsgHdr.res_id);
170 
171         assertEquals(InetAddress.parseNumericAddress("192.168.43.209"),
172                 conntrackMessage.tupleOrig.srcIp);
173         assertEquals(InetAddress.parseNumericAddress("23.211.13.26"),
174                 conntrackMessage.tupleOrig.dstIp);
175         assertEquals((byte) OsConstants.IPPROTO_TCP, conntrackMessage.tupleOrig.protoNum);
176         assertEquals((short) 44333, conntrackMessage.tupleOrig.srcPort);
177         assertEquals((short) 443, conntrackMessage.tupleOrig.dstPort);
178 
179         assertNull(conntrackMessage.tupleReply);
180 
181         assertEquals(0 /* absent */, conntrackMessage.status);
182         assertEquals(432000, conntrackMessage.timeoutSec);
183     }
184 
185     @Test
testConntrackMakeIPv4UdpTimeoutUpdate()186     public void testConntrackMakeIPv4UdpTimeoutUpdate() throws Exception {
187         assumeTrue(USING_LE);
188 
189         final byte[] udp = makeIPv4TimeoutUpdateRequestUdp();
190         assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
191     }
192 
193     @Test
testConntrackParseIPv4UdpTimeoutUpdate()194     public void testConntrackParseIPv4UdpTimeoutUpdate() throws Exception {
195         assumeTrue(USING_LE);
196 
197         final byte[] udp = makeIPv4TimeoutUpdateRequestUdp();
198         final ByteBuffer byteBuffer = ByteBuffer.wrap(udp);
199         byteBuffer.order(ByteOrder.nativeOrder());
200         final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
201         assertNotNull(msg);
202         assertTrue(msg instanceof ConntrackMessage);
203         final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
204 
205         final StructNlMsgHdr hdr = conntrackMessage.getHeader();
206         assertNotNull(hdr);
207         assertEquals(80, hdr.nlmsg_len);
208         assertEquals(makeCtType(IPCTNL_MSG_CT_NEW), hdr.nlmsg_type);
209         assertEquals((short) (StructNlMsgHdr.NLM_F_REPLACE | StructNlMsgHdr.NLM_F_REQUEST
210                 | StructNlMsgHdr.NLM_F_ACK), hdr.nlmsg_flags);
211         assertEquals(1, hdr.nlmsg_seq);
212         assertEquals(0, hdr.nlmsg_pid);
213 
214         final StructNfGenMsg nfmsgHdr = conntrackMessage.nfGenMsg;
215         assertNotNull(nfmsgHdr);
216         assertEquals((byte) OsConstants.AF_INET, nfmsgHdr.nfgen_family);
217         assertEquals((byte) StructNfGenMsg.NFNETLINK_V0, nfmsgHdr.version);
218         assertEquals((short) 0, nfmsgHdr.res_id);
219 
220         assertEquals(InetAddress.parseNumericAddress("100.96.167.146"),
221                 conntrackMessage.tupleOrig.srcIp);
222         assertEquals(InetAddress.parseNumericAddress("216.58.197.10"),
223                 conntrackMessage.tupleOrig.dstIp);
224         assertEquals((byte) OsConstants.IPPROTO_UDP, conntrackMessage.tupleOrig.protoNum);
225         assertEquals((short) 37069, conntrackMessage.tupleOrig.srcPort);
226         assertEquals((short) 443, conntrackMessage.tupleOrig.dstPort);
227 
228         assertNull(conntrackMessage.tupleReply);
229 
230         assertEquals(0 /* absent */, conntrackMessage.status);
231         assertEquals(180, conntrackMessage.timeoutSec);
232     }
233 
234     public static final String CT_V4NEW_TCP_HEX =
235             // CHECKSTYLE:OFF IndentationCheck
236             // struct nlmsghdr
237             "8C000000" +      // length = 140
238             "0001" +          // type = NFNL_SUBSYS_CTNETLINK (1) << 8 | IPCTNL_MSG_CT_NEW (0)
239             "0006" +          // flags = NLM_F_CREATE (1 << 10) | NLM_F_EXCL (1 << 9)
240             "00000000" +      // seqno = 0
241             "00000000" +      // pid = 0
242             // struct nfgenmsg
243             "02" +            // nfgen_family = AF_INET
244             "00" +            // version = NFNETLINK_V0
245             "1234" +          // res_id = 0x1234 (big endian)
246              // struct nlattr
247             "3400" +          // nla_len = 52
248             "0180" +          // nla_type = nested CTA_TUPLE_ORIG
249                 // struct nlattr
250                 "1400" +      // nla_len = 20
251                 "0180" +      // nla_type = nested CTA_TUPLE_IP
252                     "0800 0100 C0A8500C" +  // nla_type=CTA_IP_V4_SRC, ip=192.168.80.12
253                     "0800 0200 8C700874" +  // nla_type=CTA_IP_V4_DST, ip=140.112.8.116
254                 // struct nlattr
255                 "1C00" +      // nla_len = 28
256                 "0280" +      // nla_type = nested CTA_TUPLE_PROTO
257                     "0500 0100 06 000000" +  // nla_type=CTA_PROTO_NUM, proto=IPPROTO_TCP (6)
258                     "0600 0200 F3F1 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=62449 (big endian)
259                     "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
260             // struct nlattr
261             "3400" +          // nla_len = 52
262             "0280" +          // nla_type = nested CTA_TUPLE_REPLY
263                 // struct nlattr
264                 "1400" +      // nla_len = 20
265                 "0180" +      // nla_type = nested CTA_TUPLE_IP
266                     "0800 0100 8C700874" +  // nla_type=CTA_IP_V4_SRC, ip=140.112.8.116
267                     "0800 0200 6451B301" +  // nla_type=CTA_IP_V4_DST, ip=100.81.179.1
268                 // struct nlattr
269                 "1C00" +      // nla_len = 28
270                 "0280" +      // nla_type = nested CTA_TUPLE_PROTO
271                     "0500 0100 06 000000" +  // nla_type=CTA_PROTO_NUM, proto=IPPROTO_TCP (6)
272                     "0600 0200 01BB 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=443 (big endian)
273                     "0600 0300 F3F1 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=62449 (big endian)
274             // struct nlattr
275             "0800" +          // nla_len = 8
276             "0300" +          // nla_type = CTA_STATUS
277             "00000198" +      // nla_value = 0b110011000 (big endian)
278                               // IPS_CONFIRMED (1 << 3) | IPS_SRC_NAT (1 << 4) |
279                               // IPS_SRC_NAT_DONE (1 << 7) | IPS_DST_NAT_DONE (1 << 8)
280             // struct nlattr
281             "0800" +          // nla_len = 8
282             "0700" +          // nla_type = CTA_TIMEOUT
283             "00000078";       // nla_value = 120 (big endian)
284             // CHECKSTYLE:ON IndentationCheck
285     public static final byte[] CT_V4NEW_TCP_BYTES =
286             HexEncoding.decode(CT_V4NEW_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
287 
288     @Test
testParseCtNew()289     public void testParseCtNew() {
290         assumeTrue(USING_LE);
291 
292         final ByteBuffer byteBuffer = ByteBuffer.wrap(CT_V4NEW_TCP_BYTES);
293         byteBuffer.order(ByteOrder.nativeOrder());
294         final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
295         assertNotNull(msg);
296         assertTrue(msg instanceof ConntrackMessage);
297         final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
298 
299         final StructNlMsgHdr hdr = conntrackMessage.getHeader();
300         assertNotNull(hdr);
301         assertEquals(140, hdr.nlmsg_len);
302         assertEquals(makeCtType(IPCTNL_MSG_CT_NEW), hdr.nlmsg_type);
303         assertEquals((short) (StructNlMsgHdr.NLM_F_CREATE | StructNlMsgHdr.NLM_F_EXCL),
304                 hdr.nlmsg_flags);
305         assertEquals(0, hdr.nlmsg_seq);
306         assertEquals(0, hdr.nlmsg_pid);
307 
308         final StructNfGenMsg nfmsgHdr = conntrackMessage.nfGenMsg;
309         assertNotNull(nfmsgHdr);
310         assertEquals((byte) OsConstants.AF_INET, nfmsgHdr.nfgen_family);
311         assertEquals((byte) StructNfGenMsg.NFNETLINK_V0, nfmsgHdr.version);
312         assertEquals((short) 0x1234, nfmsgHdr.res_id);
313 
314         assertEquals(InetAddress.parseNumericAddress("192.168.80.12"),
315                 conntrackMessage.tupleOrig.srcIp);
316         assertEquals(InetAddress.parseNumericAddress("140.112.8.116"),
317                 conntrackMessage.tupleOrig.dstIp);
318         assertEquals((byte) OsConstants.IPPROTO_TCP, conntrackMessage.tupleOrig.protoNum);
319         assertEquals((short) 62449, conntrackMessage.tupleOrig.srcPort);
320         assertEquals((short) 443, conntrackMessage.tupleOrig.dstPort);
321 
322         assertEquals(InetAddress.parseNumericAddress("140.112.8.116"),
323                 conntrackMessage.tupleReply.srcIp);
324         assertEquals(InetAddress.parseNumericAddress("100.81.179.1"),
325                 conntrackMessage.tupleReply.dstIp);
326         assertEquals((byte) OsConstants.IPPROTO_TCP, conntrackMessage.tupleReply.protoNum);
327         assertEquals((short) 443, conntrackMessage.tupleReply.srcPort);
328         assertEquals((short) 62449, conntrackMessage.tupleReply.dstPort);
329 
330         assertEquals(0x198, conntrackMessage.status);
331         assertEquals(120, conntrackMessage.timeoutSec);
332     }
333 
334     @Test
testParseTruncation()335     public void testParseTruncation() {
336         assumeTrue(USING_LE);
337 
338         // Expect no crash while parsing the truncated message which has been truncated to every
339         // length between 0 and its full length - 1.
340         for (int len = 0; len < CT_V4NEW_TCP_BYTES.length; len++) {
341             final byte[] truncated = Arrays.copyOfRange(CT_V4NEW_TCP_BYTES, 0, len);
342 
343             final ByteBuffer byteBuffer = ByteBuffer.wrap(truncated);
344             byteBuffer.order(ByteOrder.nativeOrder());
345             final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer,
346                     OsConstants.NETLINK_NETFILTER);
347         }
348     }
349 
350     @Test
testParseTruncationWithInvalidByte()351     public void testParseTruncationWithInvalidByte() {
352         assumeTrue(USING_LE);
353 
354         // Expect no crash while parsing the message which is truncated by invalid bytes. The
355         // message has been truncated to every length between 0 and its full length - 1.
356         for (byte invalid : new byte[]{(byte) 0x00, (byte) 0xff}) {
357             for (int len = 0; len < CT_V4NEW_TCP_BYTES.length; len++) {
358                 final byte[] truncated = new byte[CT_V4NEW_TCP_BYTES.length];
359                 Arrays.fill(truncated, (byte) invalid);
360                 System.arraycopy(CT_V4NEW_TCP_BYTES, 0, truncated, 0, len);
361 
362                 final ByteBuffer byteBuffer = ByteBuffer.wrap(truncated);
363                 byteBuffer.order(ByteOrder.nativeOrder());
364                 final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer,
365                         OsConstants.NETLINK_NETFILTER);
366             }
367         }
368     }
369 
370     // Malformed conntrack messages.
371     public static final String CT_MALFORMED_HEX =
372             // CHECKSTYLE:OFF IndentationCheck
373             // <--           nlmsghr           -->|<-nfgenmsg->|<--    CTA_TUPLE_ORIG     -->|
374             // CTA_TUPLE_ORIG has no nla_value.
375             "18000000 0001 0006 00000000 00000000   02 00 0000 0400 0180"
376             // nested CTA_TUPLE_IP has no nla_value.
377             + "1C000000 0001 0006 00000000 00000000 02 00 0000 0800 0180 0400 0180"
378             // nested CTA_IP_V4_SRC has no nla_value.
379             + "20000000 0001 0006 00000000 00000000 02 00 0000 0C00 0180 0800 0180 0400 0100"
380             // nested CTA_TUPLE_PROTO has no nla_value.
381             // <--           nlmsghr           -->|<-nfgenmsg->|<--    CTA_TUPLE_ORIG
382             + "30000000 0001 0006 00000000 00000000 02 00 0000 1C00 0180 1400 0180 0800 0100"
383             //                                  -->|
384             + "C0A8500C 0800 0200 8C700874 0400 0280";
385             // CHECKSTYLE:ON IndentationCheck
386     public static final byte[] CT_MALFORMED_BYTES =
387             HexEncoding.decode(CT_MALFORMED_HEX.replaceAll(" ", "").toCharArray(), false);
388 
389     @Test
testParseMalformation()390     public void testParseMalformation() {
391         assumeTrue(USING_LE);
392 
393         final ByteBuffer byteBuffer = ByteBuffer.wrap(CT_MALFORMED_BYTES);
394         byteBuffer.order(ByteOrder.nativeOrder());
395 
396         // Expect no crash while parsing the malformed message.
397         int messageCount = 0;
398         while (byteBuffer.remaining() > 0) {
399             final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer,
400                     OsConstants.NETLINK_NETFILTER);
401             messageCount++;
402         }
403         assertEquals(4, messageCount);
404     }
405 
406     @Test
testToString()407     public void testToString() {
408         assumeTrue(USING_LE);
409 
410         final ByteBuffer byteBuffer = ByteBuffer.wrap(CT_V4NEW_TCP_BYTES);
411         byteBuffer.order(ByteOrder.nativeOrder());
412         final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
413         assertNotNull(msg);
414         assertTrue(msg instanceof ConntrackMessage);
415         final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
416 
417         // Bug: "nlmsg_flags{1536(NLM_F_MATCH))" is not correct because StructNlMsgHdr
418         // #stringForNlMsgFlags can't convert all flags (ex: NLM_F_CREATE) and can't distinguish
419         // the flags which have the same value (ex: NLM_F_MATCH <0x200> and NLM_F_EXCL <0x200>).
420         // The flags output string should be "NLM_F_CREATE|NLM_F_EXCL" in this case.
421         // TODO: correct the flag converted string once #stringForNlMsgFlags does.
422         final String expected = ""
423                 + "ConntrackMessage{"
424                 + "nlmsghdr{StructNlMsgHdr{ nlmsg_len{140}, nlmsg_type{256(IPCTNL_MSG_CT_NEW)}, "
425                 + "nlmsg_flags{1536(NLM_F_MATCH))}, nlmsg_seq{0}, nlmsg_pid{0} }}, "
426                 + "nfgenmsg{NfGenMsg{ nfgen_family{AF_INET}, version{0}, res_id{4660} }}, "
427                 + "tuple_orig{Tuple{IPPROTO_TCP: 192.168.80.12:62449 -> 140.112.8.116:443}}, "
428                 + "tuple_reply{Tuple{IPPROTO_TCP: 140.112.8.116:443 -> 100.81.179.1:62449}}, "
429                 + "status{408(IPS_CONFIRMED|IPS_SRC_NAT|IPS_SRC_NAT_DONE|IPS_DST_NAT_DONE)}, "
430                 + "timeout_sec{120}}";
431         assertEquals(expected, conntrackMessage.toString());
432     }
433 }
434