Application was interested in getting the NUD_INCOMPLETE but not received even after registering. Pls help in solving this issue.
Below is the program but failing to get NUD_INCOMPLETE. But gets below 3 events only not NUD_INCOMPLETE.
NUD_REACHABLE 0x02
NUD_STALE 0x04
NUD_NOARP 0x40
I am looking to getting IPv6 destination (even if its not resolved) when NUD_INCOMPLETE msg is received on application side.
NUD_INCOMPLETE a currently resolving cache entry
Below is the program but failing to get NUD_INCOMPLETE. But gets below 3 events only not NUD_INCOMPLETE.
NUD_REACHABLE 0x02
NUD_STALE 0x04
NUD_NOARP 0x40
I am looking to getting IPv6 destination (even if its not resolved) when NUD_INCOMPLETE msg is received on application side.
NUD_INCOMPLETE a currently resolving cache entry
C++:
1. Create NeighSocket for monitering
bool ipv6::NeighCacheMonitor::CreateNeighTableSocket()
{
neighTableFd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if(neighTableFd < 0)
{
cout << " socket() failed. err:" << errno
<< " errStr:" << std::strerror(errno));
return false;
}
struct sockaddr_nl sockNl = {};
sockNl.nl_family = AF_NETLINK;
int ret = bind(neighTableFd, (struct sockaddr*) &sockNl, sizeof(sockNl));
if(ret < 0)
{
cout << " bind() failed. err:" << errno
<< " errStr:" << std::strerror(errno));
return false;
}
return true;
}
2. Register for the msg types.
bool IPv6::NeighMonitor::SendGetNeighTableNLMsg()
{
unsigned char localbuff[256];
memset(localbuff, 0, sizeof(localbuff));
struct nlmsghdr* nl = (struct nlmsghdr*)localbuff;
nl->nlmsg_type = RTM_GETNEIGH | RTM_NEWNEIGH | RTM_DELNEIGH;
nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
// initialize len as one rt msg
struct ndmsg* nd = NULL;
nl->nlmsg_len = NLMSG_LENGTH(sizeof(*nd));
nd = (struct ndmsg*)NLMSG_DATA(nl);
nd->ndm_family = AF_INET6;
nd->ndm_ifindex = 0;
nd->ndm_state = (NUD_INCOMPLETE | NUD_REACHABLE | NUD_STALE | NUD_PROBE | NUD_DELAY
| NUD_FAILED | NUD_PERMANENT | NUD_NOARP);
nd->ndm_flags = 0;
nd->ndm_type = 0;
// send Netlink Msg
struct sockaddr_nl sa;
struct iovec iov = {(void*) nl, nl->nlmsg_len};
struct msghdr msg = {(void*)& sa, sizeof(sa), &iov, 1, NULL, 0, 0};
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
nl->nlmsg_seq = ++sequence_number;
int ret = sendmsg(neighTableFd, &msg, 0);
if(ret < 0)
{
cout << "sendmsg failed. err:" << errno
<< " errStr:" << std::strerror(errno));
return false;
}
cout << << neighTableFd << " seqNum:" << sequence_number);
....
}
3. Sepreate thread to monitor fd.
void ipv6::NeighCacheMonitor::Run()
{
while(1)
{
struct timeval tv;
tv.tv_sec = 60;
tv.tv_usec = 0;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(neighTableFd, &rfds);
int rv = select(neighTableFd, &rfds, NULL, NULL, &tv);
if(rv < 0)
{
// Error Handling
}
if(FD_ISSET(neighTableFd, &rfds))
{
recvNLMsg(neighTableFd);
}
}
}
bool ipv6::NeighCacheMonitor::recvNLMsg(int fd)
{
int len;
char recvBuffer[4096];
struct iovec iovRecv = {recvBuffer, sizeof(recvBuffer)};
struct sockaddr_nl recvSaNl;
struct msghdr recvMsgHdr;
struct nlmsghdr* recvNlMsgHdr = NULL;
recvMsgHdr.msg_name = (void*)& recvSaNl;
recvMsgHdr.msg_namelen = sizeof(recvSaNl);
recvMsgHdr.msg_iov = &iovRecv;
recvMsgHdr.msg_iovlen = 1;
recvMsgHdr.msg_control = NULL;
recvMsgHdr.msg_controllen = 0;
recvMsgHdr.msg_flags = 0;
struct ndmsg* neigh = (struct ndmsg*) NLMSG_DATA(nlMsgHdrPtr);
int length = nlMsgHdrPtr->nlmsg_len - NLMSG_LENGTH(sizeof(*neigh));
if(length < 0)
{
cout "Invalid NLMsg length:" << length);
return false;
}
len = recvmsg(fd, &recvMsgHdr, 0);
. . . .
HandleNeighMsg(recvNlMsgHdr);
}
HandleNeighMsg()
{
cout << ": NeighMsgType: " << nlMsgHdrPtr->nlmsg_type << " NeighState: " << neigh->ndm_state;
if(NUD_INCOMPLETE == nlMsgHdrPtr->nlmsg_type)
{
// Handle INCOMPLETE msg
}
}
Last edited: