top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

ICMPv6 Neighbour Solication request is not answered by linux when IPv6 address is assigned via Netlink code.

+2 votes
527 views

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.

posted May 21, 2013 by Prem Chaitanya Prathi

Share this question
Facebook Share Button Twitter Share Button LinkedIn Share Button

2 Answers

+1 vote

1) If you could show ip addr show and ip route show it would help
2) Does it respond to the fe80:: address for that system or does it not respond on IPv6 at all?
3) 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?
4) 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...

answer May 21, 2013 by anonymous
Here is the ouput for ip addr show

1: lo: <LOOPBACK,UP,LOWER_UP> 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: <NO-CARRIER,BROADCAST,MULTICAST,UP> 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: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> 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: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> 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
--------------------------------------------------------------------------------------
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.
0 votes

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?

answer May 21, 2013 by anonymous
Similar Questions
0 votes

I usually have some default rules in place on all nodes which look about like this:

-A INPUT --in-interface lo -j ACCEPT
-A OUTPUT --out-interface lo -j ACCEPT

-A INPUT -m state --state UNTRACKED -j DROP
-A FORWARD -m state --state UNTRACKED -j DROP
-A OUTPUT -m state --state UNTRACKED -j DROP

-A INPUT -m state --state INVALID -j DROP
-A FORWARD -m state --state INVALID -j DROP
-A OUTPUT -m state --state INVALID -j DROP

#handle IPsec only sources/destinations
#snip/snap

#allow incoming packets for all established and all related connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#allow incoming ICMP packets
-A INPUT --protocol icmpv6 -j ACCEPT

And the same for IPv4.

The idea with dropping the UNTRACKED/INVALID was that such packages are probably not good fellows and should stay out...

Okay... now with IPv4 everything works as expected...

But with v6 nothing works at all and I get Destination unreachable (even on pings)... I can't even reach the gateway.

When I disable dropping the untracked packets... it starts working,..even when afterwards I enable it again.
Seems that there is some connection between the host an the gateway shown then by conntrack.

Now... question is why?

0 votes

I'm afraid that I've done an incredibly stupid thing. First. I removed IPV6 from my system. Second, I upgraded to Ubuntu13.04. Third, I misplaced the instructions for deleting IPV6. Now, I evidently need IPV6 and don't know how to reverse my past sins can someone help me out? I think that I removed ipV6 by changing a configuration file and then remaking Grub.

I can't even find the configuration file in 13.04.

+3 votes

When I read wiki , its written like this

As of 6 February 2010, multihoming in the next-generation Internet Protocol (IPv6) 
was not yet standardized

Is it supported now ?

+3 votes

Is IPv6 a must for LTE? Can we have a device supporting only IPv4 or can operator launch a service with IPV4 support?

...