1 /*
2 * Copyright (C) 2020 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 @file:JvmName("NetlinkTestUtils")
18
19 package com.android.testutils
20
21 import com.android.net.module.util.netlink.NetlinkConstants.RTM_DELNEIGH
22 import com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWNEIGH
23 import libcore.util.HexEncoding
24 import libcore.util.HexEncoding.encodeToString
25 import java.net.Inet6Address
26 import java.net.InetAddress
27
28 private const val VRRP_MAC_ADDR = "00005e000164"
29
30 /**
31 * Make a RTM_NEWNEIGH netlink message.
32 */
33 @JvmOverloads
makeNewNeighMessagenull34 fun makeNewNeighMessage(
35 neighAddr: InetAddress,
36 nudState: Short,
37 linkLayerAddr: String = VRRP_MAC_ADDR
38 ) = makeNeighborMessage(
39 neighAddr = neighAddr,
40 type = RTM_NEWNEIGH,
41 nudState = nudState,
42 linkLayerAddr = linkLayerAddr
43 )
44
45 /**
46 * Make a RTM_DELNEIGH netlink message.
47 */
48 fun makeDelNeighMessage(
49 neighAddr: InetAddress,
50 nudState: Short
51 ) = makeNeighborMessage(
52 neighAddr = neighAddr,
53 type = RTM_DELNEIGH,
54 nudState = nudState
55 )
56
57 private fun makeNeighborMessage(
58 neighAddr: InetAddress,
59 type: Short,
60 nudState: Short,
61 linkLayerAddr: String = VRRP_MAC_ADDR
62 ) = HexEncoding.decode(
63 /* ktlint-disable indent */
64 // -- struct nlmsghdr --
65 // length = 88 or 76:
66 (if (neighAddr is Inet6Address) "58000000" else "4c000000") +
67 type.toLEHex() + // type
68 "0000" + // flags
69 "00000000" + // seqno
70 "00000000" + // pid (0 == kernel)
71 // struct ndmsg
72 // family (AF_INET6 or AF_INET)
73 (if (neighAddr is Inet6Address) "0a" else "02") +
74 "00" + // pad1
75 "0000" + // pad2
76 "15000000" + // interface index (21 == wlan0, on test device)
77 nudState.toLEHex() + // NUD state
78 "00" + // flags
79 "01" + // type
80 // -- struct nlattr: NDA_DST --
81 // length = 20 or 8:
82 (if (neighAddr is Inet6Address) "1400" else "0800") +
83 "0100" + // type (1 == NDA_DST, for neighbor messages)
84 // IP address:
85 encodeToString(neighAddr.address) +
86 // -- struct nlattr: NDA_LLADDR --
87 "0a00" + // length = 10
88 "0200" + // type (2 == NDA_LLADDR, for neighbor messages)
89 linkLayerAddr + // MAC Address(default == 00:00:5e:00:01:64)
90 "0000" + // padding, for 4 byte alignment
91 // -- struct nlattr: NDA_PROBES --
92 "0800" + // length = 8
93 "0400" + // type (4 == NDA_PROBES, for neighbor messages)
94 "01000000" + // number of probes
95 // -- struct nlattr: NDA_CACHEINFO --
96 "1400" + // length = 20
97 "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages)
98 "05190000" + // ndm_used, as "clock ticks ago"
99 "05190000" + // ndm_confirmed, as "clock ticks ago"
100 "190d0000" + // ndm_updated, as "clock ticks ago"
101 "00000000", // ndm_refcnt
102 false /* allowSingleChar */)
103 /* ktlint-enable indent */
104
105 /**
106 * Convert a [Short] to a little-endian hex string.
107 */
108 private fun Short.toLEHex() = String.format("%04x", java.lang.Short.reverseBytes(this))
109