ICMPv6 Neighbour Solication Request Is Not Answered By Linux When IPv6 Address Is Assigned Via Netlink Code.

Home » CentOS » ICMPv6 Neighbour Solication Request Is Not Answered By Linux When IPv6 Address Is Assigned Via Netlink Code.
CentOS 4 Comments

Hi,

I have a process which is running as a linux service and assigns IP addresses using netlink to configued interface in linux. For IPv4 addresses i do not see any issue with this assignment.

When i try to assign an IPv6 address, the address gets assigned successfully to the interface, but the Neighbour Solication request received for that address is not responded with and hence ping6 from a different machine doesn’t work.

When i take the same netlink code and run it in a sample program the address gets assigned and the Neighbour solicitation is responded with a advertisement and hence ping6 works.

IP assigned by the program : 7000::15/32
IP on client machine from where ping6 is done : 7000::17/32.

Bot machines are connected to same Layer-2 switch.

I have flushed the ip6tables on both the machines just to rule out any firewall issues.

Thanks, Kevin Peterson

4 thoughts on - ICMPv6 Neighbour Solication Request Is Not Answered By Linux When IPv6 Address Is Assigned Via Netlink Code.

  • If you could show ip addr show and ip route show it would help

    Does it respond to the fe80:: address for that system or does it not respond on IPv6 at all?

    Just for clarity’s sake (since assumptions often lead to issues) this sample program is being run on the same system? Could you post the sample code?

    Have you changed these addresses for the purpose of email? Given that
    7000:: is well outside of the addresses currently in RFCs there could be an edge case bug surrounding that … what if you use an appropriate ULA
    address (fc00::/7) – does the issue appear in that case? You have a very odd subnet mask applied for that IPv6 address … the general expectation is a single subnet is /64 …and in fact /32 is huge given that a /32 is generally expected to be assigned to a complete ISP with most end users being between a /48 and a /56 in assignment… So there could be an edge case bug as well given the size of subnet being associated…

  • Hi Janes,

    Here is the ouput for ip addr show

    1: lo: mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    valid_lft forever preferred_lft forever
    2: eth0: mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
    link/ether 4c:72:b9:66:02:7f brd ff:ff:ff:ff:ff:ff
    inet 172.16.8.50/16 brd 172.16.255.255 scope global eth0
    inet6 fe80::4e72:b9ff:fe66:27f/64 scope link
    valid_lft forever preferred_lft forever
    3: eth1: mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
    link/ether 00:03:ba:b1:ad:64 brd ff:ff:ff:ff:ff:ff
    4: eth2:
    mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
    link/ether 00:03:ba:b1:ad:64 brd ff:ff:ff:ff:ff:ff
    5: eth3:
    mtu 1500 qdisc pfifo_fast master bond1 state UP qlen 1000
    link/ether 00:03:ba:b1:ad:66 brd ff:ff:ff:ff:ff:ff
    6: eth4:
    mtu 1500 qdisc pfifo_fast master bond1 state UP qlen 1000
    link/ether 00:03:ba:b1:ad:66 brd ff:ff:ff:ff:ff:ff
    9: bond0:
    mtu 1500 qdisc noqueue state UP
    link/ether 00:03:ba:b1:ad:64 brd ff:ff:ff:ff:ff:ff
    inet 172.16.13.100/16 brd 172.16.255.255 scope global bond0
    inet6 7000::15/32 scope global
    valid_lft forever preferred_lft forever
    inet6 fe80::203:baff:feb1:ad64/64 scope link
    valid_lft forever preferred_lft forever
    10: bond1:
    mtu 1500 qdisc noqueue state UP
    link/ether 00:03:ba:b1:ad:66 brd ff:ff:ff:ff:ff:ff
    inet 10.1.8.101/24 brd 10.1.8.255 scope global bond1
    inet6 fe80::203:baff:feb1:ad66/64 scope link
    valid_lft forever preferred_lft forever Output of ip route show is below:
    [root@hadev1 ~]# ip route show
    10.1.8.0/24 dev bond1 proto kernel scope link src 10.1.8.101
    169.254.0.0/16 dev eth0 scope link metric 1002
    169.254.0.0/16 dev bond0 scope link metric 1009
    169.254.0.0/16 dev bond1 scope link metric 1010
    172.16.0.0/16 dev bond0 proto kernel scope link src 172.16.13.100
    172.16.0.0/16 dev eth0 proto kernel scope link src 172.16.8.50
    default via 172.16.6.250 dev bond0
    ————————————————————————————

  • Please don’t top post.

    Given we are talking about IPv6 – my apologies I forgot ip route show defaults to v4 information … If you could redo with ip -6 route show that’d be great…

    Whilst testing (and in general) stick to /64 assignments – that is the expectation and best place to start … and similarly either use a provided IP space (from a tunnel broker if need be) or use ULA to avoid edge cases there … if that works then you can test outside the expected areas …

    With the behaviour you mention I’m curious as to whether an entry for the network is being entered into the table at all on the system the code snippet is run on versus the one where ip addr add is used…

    As an example from my system after doing an ip addr add fc00::::17/64 dev eth0 the routing table looks like:

    $ ip -6 route show
    2001::/32 dev teredo proto kernel metric 256
    fc00::/64 dev eth0 proto kernel metric 256
    fe80::/64 dev eth0 proto kernel metric 256
    fe80::/64 dev teredo proto kernel metric 256
    default dev teredo metric 1029

    Check before and after you have done your code snippet… You might find it’ll work fine if you preconfigure the routing table with that subnet (or just add another ipv6 address on that subnet to have it done automatically that way)…

    If no route for that network gets entered it may not be surprising not to be able to ping until the first machine has and the neighbour is discovered that way…

    Are you also 100% sure you are not dropping any ICMPv6 packets between systems – no transparent firewalls or anything?

  • Hi James,

    I did not mean to top-post. I was commenting via some other website which did a top-post i guess. Also it did not post the complete information i wanted to provide to you. Then i had to search in the internet to see where that website had posted my question.

    Here is the other info you wanted (reply to your previous queries 2,3,4):

    2. I get a response for fe80:: address.
    3. Sample program is being run on the same machine.
    Here is the snippet of code i am using to assign IP address:

    int AssignIpAddressToInterface(const char *interfaceName, const char *ipAddress, unsigned char routingPrefix, bool assign) {

    int addrFamily = GetAddrFamily(ipAddress);

    if (addrFamily == -1)
    return addrFamily;

    struct RtNetlinkIpAddressReq rtNetlinkIpAddressReq;

    int fd;
    struct sockaddr_nl la;
    struct sockaddr_nl pa;
    struct msghdr msgHdr;
    struct iovec ioVec;

    int rc;

    int ifAddrMsgLen;
    struct rtattr *pRtAttr;

    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);

    bzero(&la, sizeof (la));
    la.nl_family = AF_NETLINK;
    la.nl_pid = getpid();
    bind(fd, (struct sockaddr*) &la, sizeof (la));

    bzero(&rtNetlinkIpAddressReq, sizeof (rtNetlinkIpAddressReq));

    ifAddrMsgLen = sizeof (struct ifaddrmsg);

    pRtAttr = (struct rtattr *) rtNetlinkIpAddressReq.buf;
    pRtAttr->rta_type = IFA_ADDRESS;

    if (addrFamily == AF_INET) {
    pRtAttr->rta_len = sizeof (struct rtattr) + 4;
    inet_pton(AF_INET, ipAddress,
    ((char *) pRtAttr) + sizeof (struct rtattr));
    } else if (addrFamily == AF_INET6) {
    pRtAttr->rta_len = sizeof (struct rtattr) + 16;
    inet_pton(AF_INET6, ipAddress,
    ((char *) pRtAttr) + sizeof (struct rtattr));
    }

    ifAddrMsgLen += pRtAttr->rta_len;

    pRtAttr = (struct rtattr *) (((char *) pRtAttr)
    + pRtAttr->rta_len);
    pRtAttr->rta_type = IFA_LOCAL;
    if (addrFamily == AF_INET) {
    pRtAttr->rta_len = sizeof (struct rtattr) + 4;
    inet_pton(AF_INET, ipAddress,
    ((char *) pRtAttr) + sizeof (struct rtattr));
    } else if (addrFamily == AF_INET6) {
    pRtAttr->rta_len = sizeof (struct rtattr) + 16;
    inet_pton(AF_INET6, ipAddress,
    ((char *) pRtAttr) + sizeof (struct rtattr));
    }

    ifAddrMsgLen += pRtAttr->rta_len;

    rtNetlinkIpAddressReq.nl.nlmsg_len = NLMSG_LENGTH(ifAddrMsgLen);
    rtNetlinkIpAddressReq.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_APPEND;

    if (assign)
    rtNetlinkIpAddressReq.nl.nlmsg_type = RTM_NEWADDR;
    else
    rtNetlinkIpAddressReq.nl.nlmsg_type = RTM_DELADDR;

    if (addrFamily == AF_INET)
    rtNetlinkIpAddressReq.rt.ifa_family = AF_INET;
    else if (addrFamily == AF_INET6)
    rtNetlinkIpAddressReq.rt.ifa_family = AF_INET6;

    rtNetlinkIpAddressReq.rt.ifa_prefixlen = routingPrefix;
    rtNetlinkIpAddressReq.rt.ifa_flags = IFA_F_PERMANENT;
    rtNetlinkIpAddressReq.rt.ifa_scope = RT_SCOPE_UNIVERSE;

    unsigned index = if_nametoindex(interfaceName);
    rtNetlinkIpAddressReq.rt.ifa_index = index;

    bzero(&pa, sizeof (pa));
    pa.nl_family = AF_NETLINK;

    bzero(&msgHdr, sizeof (msgHdr));
    msgHdr.msg_name = (void *) &pa;
    msgHdr.msg_namelen = sizeof (pa);
    ioVec.iov_base = (void *) &rtNetlinkIpAddressReq.nl;
    ioVec.iov_len = rtNetlinkIpAddressReq.nl.nlmsg_len;
    msgHdr.msg_iov = &ioVec;
    msgHdr.msg_iovlen = 1;

    rc = sendmsg(fd, &msgHdr, 0);

    close(fd);

    if (rc == -1) {
    if (assign)
    printf(“IP address %s ASSIGNMENT with routing prefix %d on interface %s failed”, ipAddress, routingPrefix, interfaceName);
    else
    printf(“IP address %s UNASSIGNMENT with routing prefix %d on interface %s failed”, ipAddress, routingPrefix, interfaceName);
    } else {
    if (assign)
    printf(“Successfully ASSIGNED IP address %s with routing prefix %d on interface %s”, ipAddress, routingPrefix, interfaceName);
    else
    printf(“Successfully UNASSIGNED IP address %s with routing prefix %d on interface %s”, ipAddress, routingPrefix, interfaceName);
    }

    printf(“<<<<<<<<<< Exiting AvailabilityManager::AssignIpAddressToInterface() <<<<<<<<<<");

    return rc;
    }
    ———————————————————————————————-
    4. I did not change these address for email. This is just to test the ipv6 capability for the product i am working on..hence i chose such addresses. I used an ULA address suggested by you but still the behaviour is same. I also tried with a 64 bit subnet and the behaviour is same.

    Also there is one more observation i forgot to mention:
    Let us say the Machine in which i am running the code (which assigns IP) has an IPV6 address fc00::15/7 as m1 and the machine from which i am trying to reach this has fc00::17/7 is m2.

    When i ping6 m1 from m2 i get "From fc00::17 icmp_seq=2 Destination unreachable: Address unreachable".

    But when i ping6 m2 from m1 i am able to reach it. The IP address of m2 is manually added using ip addr add command. After this the ping6 from m1 to m2 also starts working.
    —————————————–
    Also for the ip -6 route output here it is:
    [root@hadev1 ~]# ip -6 route show
    unreachable ::/96 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable ::ffff:0.0.0.0/96 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 2002:a00::/24 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 2002:7f00::/24 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 2002:a9fe::/32 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 2002:ac10::/28 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 2002:c0a8::/32 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 2002:e000::/19 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    unreachable 3ffe:ffff::/32 dev lo metric 1024 error -101 mtu 16436 advmss 16376 hoplimit 4294967295
    fc00::/7 dev bond0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 4294967295
    fe80::/64 dev bond0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 4294967295
    fe80::/64 dev bond1 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 4294967295
    fe80::/64 dev eth0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 4294967295

LEAVE A COMMENT