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

Tue May 21 15:48:28 UTC 2013
Kevin Peterson <qh.resu01 at gmail.com>

Hi Janes,

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 at 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.

Regards,


On Tue, May 21, 2013 at 4:19 PM, James Hogarth <james.hogarth at gmail.com>wrote:

> On 21 May 2013 07:10, Kevin Peterson <qh.resu01 at gmail.com> wrote:
>
> > 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.
> >
> >
> If you could show ip addr show and ip route show it would help
>
>
> > 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.
> >
> >
> Does it respond to the fe80:: address for that system or does it not
> respond on IPv6 at all?
>
>
> > 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.
> >
> >
> 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?
>
>
> > IP assigned by the program : 7000::15/32
> > IP on client machine from where ping6 is done : 7000::17/32.
> >
> >
> 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...
>
>
> >
> >
> _______________________________________________
> CentOS mailing list
> CentOS at centos.org
> http://lists.centos.org/mailman/listinfo/centos
>