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