July 28, 2018

How to use Netlink to get ipv6 neighbors

1. open netlink socket
2. send request to get neighbors
3. parse the response


The response is in the following format
[ netlink msg ] ... [ netlink msg ]


use the Macros defined in "man 3 netlink" to iterate through the messages. Each netlink message has a header "struct nlmsghdr *", defined in "man 7 netlink".

The netlink message for getting ipv6 neighbors is defined in "man 7 rtnetlink"

for ipv6 neighbors message, each netlink msg block has the following format:
  netlink-msg-header | neighbor-discover-msg-header (struct ndmsg) | route-attributes (struct rtattr) | more route-attributes...


Each route-attributes has the following format:
  header (struct rtattr) | data


The types of rtattr are defined in /usr/include/linux/neighbour.h, with the commons are:
  NDA_DST: data is IP address
  NDA_LLADDR: data is MAC address
  NDA_CACHEINFO: data is struct nda_cacheinfo



Example NetLink payload parsing (not showing nlmsghdr):

0a 00 00 00  :  inet family
02 00 00 00  : ifindex
04 00  : state
00 : flags
01 : type


14 00 : rtattr len
01 00 : type
fe 80 00 00 00 00 00 00 b6 ef fa ff fe d0 fe 76 : Ipv6 address


0a 00 : rtattr len
02 00 : type
b4 ef fa d0 fe 76 : mac


00 00  //padding

08 00  //probe ?
04 00
00 00 00 00


14 00 //rtattr len
03 00 //cache info
6b a8 e8 01 fb 90 e8 01
6b b9 69 00 00 00 00 00

March 31, 2018

CAVEAT: golang uint to string conversion

In golang, you can cast a "uint8" value  to "string".

Be aware that
  if the uint8 x <= 127, string(x) is the ASCII char of the value x,
  if the uint8 x >128, string(x) is 2 bytes long, because of UTF-8