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_LOCALb9drth-> 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_LOCALrth-> 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_LOCALrth-> 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
- :inet6のRTM_GETADDRについては
は、カーネルがIFA_ADDRESS(:inet6_fill_ifaddr()addrconf.c)で応答を要求します'それを' fe80 ::/10'と比較してください。一致する場合は、リンクローカルアドレスです。 –
これは私が手に入れたいものではありません。 –
あなたはそれを探していますか? –