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.

Reply via email to