title: Filter IPv6 local address using netlink
body: <p>I write C code using netlink to get information about IP route table and detect new IP address of given interface.
  Using IPv4, I can filter local address using 'IFA_LOCAL'.
  But using IPv6, I can't get local address: <code>rta_type</code> is never equal to <code>IFA_LOCAL</code>, even for local address.</p>
  <p>The used code is the following:</p>
  <pre><code>int main(void)
  {
      struct {
          struct nlmsghdr hdr;
          struct ifaddrmsg msg;
      } req;
      struct sockaddr_nl addr;
      int sock[2];
  
      memset(&amp;addr, 0, sizeof(addr));
      memset(&amp;req, 0, sizeof(req));
  
      if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
          CWMP_LOG(ERROR,&quot;couldn't open NETLINK_ROUTE socket&quot;);
          return -1;
      }
  
      addr.nl_family = AF_NETLINK;
      addr.nl_groups = RTMGRP_IPV6_IFADDR;// |RTMGRP_IPV6_IFADDR;
      if ((bind(sock[0], (struct sockaddr_in6 *)&amp;addr, sizeof(addr))) == -1) {
          CWMP_LOG(ERROR,&quot;couldn't bind netlink socket&quot;);
          return -1;
      }
  
      netlink_event.fd = sock[0];
      if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) {
          CWMP_LOG(ERROR,&quot;couldn't open NETLINK_ROUTE socket&quot;);
          return -1;
      }
  
      req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
      req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
      req.hdr.nlmsg_type = RTM_GETADDR;
      req.msg.ifa_family = AF_INET6;
  
      if ((send(sock[1], &amp;req, req.hdr.nlmsg_len, 0)) == -1) {
          CWMP_LOG(ERROR,&quot;couldn't send netlink socket&quot;);
          return -1;
      }
  
      struct nlmsghdr *nlh;
      char buffer[BUFSIZ];
      int msg_size;
  
      memset(&amp;buffer, 0, sizeof(buffer));
  
      nlh = (struct nlmsghdr *)buffer;
      if ((msg_size = recv(sock[1], nlh, BUFSIZ, 0)) == -1) {
          CWMP_LOG(ERROR,&quot;error receiving netlink message&quot;);
          return;
      }
  
      while (msg_size &gt; sizeof(*nlh)) {
          int len = nlh-&gt;nlmsg_len;
          int req_len = len - sizeof(*nlh);
  
          if (req_len &lt; 0 || len &gt; msg_size) {
              CWMP_LOG(ERROR,&quot;error reading netlink message&quot;);
              return;
          }
  
          if (!NLMSG_OK(nlh, msg_size)) {
              CWMP_LOG(ERROR,&quot;netlink message is not NLMSG_OK&quot;);
              return;
          }
  
          if (nlh-&gt;nlmsg_type == RTM_NEWADDR) {
              printf(&quot;new addr \n&quot;);
              struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
              struct rtattr *rth = IFA_RTA(ifa);
              int rtl = IFA_PAYLOAD(nlh);
              char if_name[IFNAMSIZ], if_addr[INET6_ADDRSTRLEN];
              char *c;
              struct in6_addr *in6p;
  
              memset(&amp;if_name, 0, sizeof(if_name));
              memset(&amp;if_addr, 0, sizeof(if_addr));
  
              while (rtl &amp;&amp; RTA_OK(rth, rtl)) {
                  printf(&quot;rth-&gt;rta_type %d \n&quot;, rth-&gt;rta_type);
                  in6p = (struct in6_addr *)RTA_DATA(rth);
                  printf(&quot;addr1: &quot; NIP6_FMT &quot;\n&quot;,NIP6(*in6p));
                  if (rth-&gt;rta_type != IFA_LOCAL) {
                      printf(&quot;########NOT IFA_LOCAL ############\n&quot;);
                      rth = RTA_NEXT(rth, rtl);
                      continue;
                  }
                  printf(&quot;======IFA_LOCAL======\n&quot;);
                  rth = RTA_NEXT(rth, rtl);                   
              }
          }   
          msg_size -= NLMSG_ALIGN(len);
          nlh = (struct nlmsghdr*)((char*)nlh + NLMSG_ALIGN(len));
      }
      return 0;
  }
  </code></pre>
  <p>And the trace of execution is the following:</p>
  <pre class="lang-text prettyprint-override"><code>rth-&gt;rta_type 6 
  addr1: 0000:0e0e:0000:1c1e:0031:15c7:0031:15c7
  ########NOT IFA_LOCAL ############
  new addr 
  rth-&gt;rta_type 1 
  addr1: fd59:ca3e:bd63:0000:0222:07ff:fe41:b9d6
  ########NOT IFA_LOCAL ############
  rth-&gt;rta_type 6 
  addr1: 0000:068c:0000:1ba4:0030:e60b:0030:e60b
  ########NOT IFA_LOCAL ############
  new addr 
  rth-&gt;rta_type 1 
  addr1: 2001:1338:000a:0000:0000:0000:0000:0196
  ########NOT IFA_LOCAL ############
  rth-&gt;rta_type 6 
  addr1: ffff:ffff:ffff:ffff:0005:a828:0005:a828
  ########NOT IFA_LOCAL ############
  new addr 
  rth-&gt;rta_type 1 
  addr1: fe80:0000:0000:0000:0222:07ff:fe41:b9d6
  ########NOT IFA_LOCAL ############
  rth-&gt;rta_type 6 
  addr1: ffff:ffff:ffff:ffff:0005:a826:0005:a826
  ########NOT IFA_LOCAL ############
  new addr 
  rth-&gt;rta_type 1 
  addr1: fe80:0000:0000:0000:0222:07ff:fe41:b9d7
  ########NOT IFA_LOCAL ############
  </code></pre>