2016-09-22 4 views
1

netlinkを使用してCコードを書き、ip routeテーブルに関する情報を取得し、givedインターフェイスの新しいIPアドレスを検出します。 IPv4を使用して、 'IFA_LOCAL'を使用してローカルアドレスをフィルタリングできます。 しかし、IPv6を使用すると、私はローカルアドレスを取得できません。ローカルアドレスの場合でも、rta_typeは 'IFA_LOCAL'に等しくないnetlinkを使用したipv6ローカルアドレス

使用コードは以下の通りです:

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 is 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; 
} 

と実行のトレースは以下の通りです: rth-> rta_type 6 ADDR1:0000:0e0e:0000:1C1E:0031:0031:15c7: 15c7

##、NOT IFA_LOCAL

新しいaddrの rth-> rta_type 1 ADDR1:fd59:ca3e:bd63:0000:0222:07FF:fe41:

##、NOT IFA_LOCALb9d

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

##、NOT IFA_LOCAL

新しいaddrの rth-> rta_type 1 ADDR1:1338:2001 :000A:0000:0000:0000:0000:0196

## NOT IFA_LOCAL

rth-> rta_type 6 ADDR1:FFFF:FFFF:FFFF:FFFF:0005:A828:0005:A828

## IFA_LOCALでない

新しい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

新しいaddrの rth-> rta_type 1 ADDR1:FE80:0222:0000:0000 0000 07FF:fe41:b9d7

# #NOT IFA_LOCAL
+0

- :inet6のRTM_GETADDRについては

/* * Important comment: * IFA_ADDRESS is prefix address, rather than local interface address. * It makes no difference for normally configured broadcast interfaces, * but for point-to-point IFA_ADDRESS is DESTINATION address, * local address is supplied in IFA_LOCAL attribute. */ enum { IFA_UNSPEC, IFA_ADDRESS, IFA_LOCAL, IFA_LABEL, IFA_BROADCAST, IFA_ANYCAST, IFA_CACHEINFO, IFA_MULTICAST, __IFA_MAX, }; 

は、カーネルがIFA_ADDRESS(:inet6_fill_ifaddr()addrconf.c)で応答を要求します'それを' fe80 ::/10'と比較してください。一致する場合は、リンクローカルアドレスです。 –

+0

これは私が手に入れたいものではありません。 –

+0

あなたはそれを探していますか? –

答えて

0

r "IFA_ADDRESS"。ブロードキャストインタフェースの場合、IFA_LOCALとIFA_ADDRESSは同じ意味を持ちます。以下は、カーネルif_addr.hのコードスニペットです。あなたはリンクローカルアドレスを探している場合は、単に `/ 10でアドレスをマスク

nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) 
関連する問題