On 6/13/19 2:07 AM, Hoang Le wrote: > @@ -119,6 +121,74 @@ static int generate_multicast(short af, char *buf, int > bufsize) > return 0; > } > > +static struct ifreq ifr = {};
you don't need to initialize globals, but you could pass a a struct as the arg to the filter here which is both the addr buffer and the ifindex of interest. > +static int nl_dump_addr_filter(struct nlmsghdr *nlh, void *arg) > +{ > + struct ifaddrmsg *ifa = NLMSG_DATA(nlh); > + char *r_addr = (char *)arg; > + int len = nlh->nlmsg_len; > + struct rtattr *addr_attr; > + > + if (ifr.ifr_ifindex != ifa->ifa_index) > + return 0; > + > + if (strlen(r_addr) > 0) > + return 1; > + > + addr_attr = parse_rtattr_one(IFA_ADDRESS, IFA_RTA(ifa), > + len - NLMSG_LENGTH(sizeof(*ifa))); > + if (!addr_attr) > + return 0; > + > + if (ifa->ifa_family == AF_INET) { > + struct sockaddr_in ip4addr; > + memcpy(&ip4addr.sin_addr, RTA_DATA(addr_attr), > + sizeof(struct in_addr)); > + if (inet_ntop(AF_INET, &ip4addr.sin_addr, r_addr, > + INET_ADDRSTRLEN) == NULL) > + return 0; > + } else if (ifa->ifa_family == AF_INET6) { > + struct sockaddr_in6 ip6addr; > + memcpy(&ip6addr.sin6_addr, RTA_DATA(addr_attr), > + sizeof(struct in6_addr)); > + if (inet_ntop(AF_INET6, &ip6addr.sin6_addr, r_addr, > + INET6_ADDRSTRLEN) == NULL) > + return 0; > + } > + return 1; > +} > + > +static int cmd_bearer_validate_and_get_addr(const char *name, char *r_addr) > +{ > + struct rtnl_handle rth ={ .fd = -1 }; space between '={' > + > + memset(&ifr, 0, sizeof(ifr)); > + if (!name || !r_addr || get_ifname(ifr.ifr_name, name)) > + return 0; > + > + ifr.ifr_ifindex = ll_name_to_index(ifr.ifr_name); > + if (!ifr.ifr_ifindex) > + return 0; > + > + /* remove from cache */ > + ll_drop_by_index(ifr.ifr_ifindex); why the call to ll_drop_by_index? doing so means that ifindex is looked up again. > + > + if (rtnl_open(&rth, 0) < 0) > + return 0; > + > + if (rtnl_addrdump_req(&rth, AF_UNSPEC, 0) < 0) { If you pass a filter here to set ifa_index, this command on newer kernels will be much more efficient. See ipaddr_dump_filter. > + rtnl_close(&rth); > + return 0; > + } > + > + if (rtnl_dump_filter(&rth, nl_dump_addr_filter, r_addr) < 0) { > + rtnl_close(&rth); > + return 0; > + } > + rtnl_close(&rth); > + return 1; > +} it would better to have 1 exit with the rtnl_close and return rc based on above.