c - ipv6 local address using netlink -


i write c code using netlink information ip route table , detect new ip address of gived interface. using ipv4, can filter local address using 'ifa_local'. using ipv6, can't local address. rta_type never equal 'ifa_local' local address.

the used code following:

int main(void) {     struct {         struct nlmsghdr hdr;         struct ifaddrmsg msg;     } req;     struct sockaddr_nl addr;     int sock[2];      memset(&addr, 0, sizeof(addr));     memset(&req, 0, sizeof(req));      if ((sock[0] = socket(pf_netlink, sock_raw, netlink_route)) == -1) {         cwmp_log(error,"couldn't open netlink_route socket");         return -1;     }      addr.nl_family = af_netlink;     addr.nl_groups = rtmgrp_ipv6_ifaddr;// |rtmgrp_ipv6_ifaddr;     if ((bind(sock[0], (struct sockaddr_in6 *)&addr, sizeof(addr))) == -1) {         cwmp_log(error,"couldn't bind netlink socket");         return -1;     }      netlink_event.fd = sock[0];     if ((sock[1] = socket(pf_netlink, sock_dgram, netlink_route)) == -1) {         cwmp_log(error,"couldn't open netlink_route socket");         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], &req, req.hdr.nlmsg_len, 0)) == -1) {         cwmp_log(error,"couldn't send netlink socket");         return -1;     }      struct nlmsghdr *nlh;     char buffer[bufsiz];     int msg_size;      memset(&buffer, 0, sizeof(buffer));      nlh = (struct nlmsghdr *)buffer;     if ((msg_size = recv(sock[1], nlh, bufsiz, 0)) == -1) {         cwmp_log(error,"error receiving netlink message");         return;     }      while (msg_size > sizeof(*nlh)) {         int len = nlh->nlmsg_len;         int req_len = len - sizeof(*nlh);          if (req_len < 0 || len > msg_size) {             cwmp_log(error,"error reading netlink message");             return;         }          if (!nlmsg_ok(nlh, msg_size)) {             cwmp_log(error,"netlink message not nlmsg_ok");             return;         }          if (nlh->nlmsg_type == rtm_newaddr) {             printf("new addr \n");             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(&if_name, 0, sizeof(if_name));             memset(&if_addr, 0, sizeof(if_addr));              while (rtl && rta_ok(rth, rtl)) {                 printf("rth->rta_type %d \n", rth->rta_type);                 in6p = (struct in6_addr *)rta_data(rth);                 printf("addr1: " nip6_fmt "\n",nip6(*in6p));                 if (rth->rta_type != ifa_local) {                     printf("########not ifa_local ############\n");                     rth = rta_next(rth, rtl);                     continue;                 }                 printf("======ifa_local======\n");                 rth = rta_next(rth, rtl);                                }         }            msg_size -= nlmsg_align(len);         nlh = (struct nlmsghdr*)((char*)nlh + nlmsg_align(len));     }     return 0; } 

and trace of execution following: rth->rta_type 6 addr1: 0000:0e0e:0000:1c1e:0031:15c7:0031:15c7

##not ifa_local

new addr rth->rta_type 1 addr1: fd59:ca3e:bd63:0000:0222:07ff:fe41:b9d6

##not ifa_local

rth->rta_type 6 addr1: 0000:068c:0000:1ba4:0030:e60b:0030:e60b

##not ifa_local

new addr rth->rta_type 1 addr1: 2001:1338:000a:0000:0000:0000:0000:0196

##not ifa_local

rth->rta_type 6 addr1: ffff:ffff:ffff:ffff:0005:a828:0005:a828

##not ifa_local

new addr rth->rta_type 1 addr1: fe80:0000:0000:0000:0222:07ff:fe41:b9d6

##not ifa_local

rth->rta_type 6 addr1: ffff:ffff:ffff:ffff:0005:a826:0005:a826

##not ifa_local

new addr rth->rta_type 1 addr1: fe80:0000:0000:0000:0222:07ff:fe41:b9d7

##not ifa_local

try "ifa_address". broadcast interfaces, ifa_local , ifa_address means same. here code snippet kernel if_addr.h.

/*  * important comment:  * ifa_address prefix address, rather local interface address.  * makes no difference configured broadcast interfaces,  * point-to-point ifa_address destination address,  * local address supplied in ifa_local attribute.  */ enum {     ifa_unspec,     ifa_address,     ifa_local,     ifa_label,     ifa_broadcast,     ifa_anycast,     ifa_cacheinfo,     ifa_multicast,     __ifa_max, }; 

for inet6 rtm_getaddr requests kernel responds ifa_address (addrconf.c:inet6_fill_ifaddr()):-

nla_put(skb, ifa_address, 16, &ifa->addr) 

Comments

Popular posts from this blog

unity3d - Rotate an object to face an opposite direction -

angular - Is it possible to get native element for formControl? -

javascript - Why jQuery Select box change event is now working? -