]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/ipaddress.c
Merge branch 'iproute2-master' into iproute2-next
[mirror_iproute2.git] / ip / ipaddress.c
index 955ef72e5f89a47644dbdbc873ae9f2cc5c8f579..aecc9a1d070ef859de54a61551d619168915143f 100644 (file)
@@ -34,7 +34,6 @@
 #include "utils.h"
 #include "ll_map.h"
 #include "ip_common.h"
-#include "xdp.h"
 #include "color.h"
 
 enum {
@@ -594,11 +593,18 @@ static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
        }
 }
 
-static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
-                              const struct rtattr *carrier_changes)
+static void __print_link_stats(FILE *fp, struct rtattr *tb[])
 {
+       const struct rtattr *carrier_changes = tb[IFLA_CARRIER_CHANGES];
+       struct rtnl_link_stats64 _s, *s = &_s;
+       int ret;
+
+       ret = get_rtnl_link_stats_rta(s, tb);
+       if (ret < 0)
+               return;
+
        if (is_json_context()) {
-               open_json_object("stats64");
+               open_json_object((ret == sizeof(*s)) ? "stats64" : "stats");
 
                /* RX stats */
                open_json_object("rx");
@@ -610,8 +616,7 @@ static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
                print_uint(PRINT_JSON, "multicast", NULL, s->multicast);
                if (s->rx_compressed)
                        print_uint(PRINT_JSON,
-                                  "compressed",
-                                  NULL, s->rx_compressed);
+                                  "compressed", NULL, s->rx_compressed);
 
                /* RX error stats */
                if (show_stats > 1) {
@@ -648,8 +653,7 @@ static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
                print_uint(PRINT_JSON, "collisions", NULL, s->collisions);
                if (s->tx_compressed)
                        print_uint(PRINT_JSON,
-                                  "compressed",
-                                  NULL, s->tx_compressed);
+                                  "compressed", NULL, s->tx_compressed);
 
                /* TX error stats */
                if (show_stats > 1) {
@@ -669,154 +673,6 @@ static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
                                print_uint(PRINT_JSON, "carrier_changes", NULL,
                                           rta_getattr_u32(carrier_changes));
                }
-               close_json_object();
-               close_json_object();
-
-       } else {
-               /* RX stats */
-               fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
-                       s->rx_compressed ? "compressed" : "", _SL_);
-
-               fprintf(fp, "    ");
-               print_num(fp, 10, s->rx_bytes);
-               print_num(fp, 8, s->rx_packets);
-               print_num(fp, 7, s->rx_errors);
-               print_num(fp, 7, s->rx_dropped);
-               print_num(fp, 7, s->rx_over_errors);
-               print_num(fp, 7, s->multicast);
-               if (s->rx_compressed)
-                       print_num(fp, 7, s->rx_compressed);
-
-               /* RX error stats */
-               if (show_stats > 1) {
-                       fprintf(fp, "%s", _SL_);
-                       fprintf(fp, "    RX errors: length   crc     frame   fifo    missed%s%s",
-                               s->rx_nohandler ? "   nohandler" : "", _SL_);
-
-                       fprintf(fp, "               ");
-                       print_num(fp, 8, s->rx_length_errors);
-                       print_num(fp, 7, s->rx_crc_errors);
-                       print_num(fp, 7, s->rx_frame_errors);
-                       print_num(fp, 7, s->rx_fifo_errors);
-                       print_num(fp, 7, s->rx_missed_errors);
-                       if (s->rx_nohandler)
-                               print_num(fp, 7, s->rx_nohandler);
-
-               }
-               fprintf(fp, "%s", _SL_);
-
-               /* TX stats */
-               fprintf(fp, "    TX: bytes  packets  errors  dropped carrier collsns %s%s",
-                       s->tx_compressed ? "compressed" : "", _SL_);
-
-               fprintf(fp, "    ");
-               print_num(fp, 10, s->tx_bytes);
-               print_num(fp, 8, s->tx_packets);
-               print_num(fp, 7, s->tx_errors);
-               print_num(fp, 7, s->tx_dropped);
-               print_num(fp, 7, s->tx_carrier_errors);
-               print_num(fp, 7, s->collisions);
-               if (s->tx_compressed)
-                       print_num(fp, 7, s->tx_compressed);
-
-               /* TX error stats */
-               if (show_stats > 1) {
-                       fprintf(fp, "%s", _SL_);
-                       fprintf(fp, "    TX errors: aborted  fifo   window heartbeat");
-                       if (carrier_changes)
-                               fprintf(fp, " transns");
-                       fprintf(fp, "%s", _SL_);
-
-                       fprintf(fp, "               ");
-                       print_num(fp, 8, s->tx_aborted_errors);
-                       print_num(fp, 7, s->tx_fifo_errors);
-                       print_num(fp, 7, s->tx_window_errors);
-                       print_num(fp, 7, s->tx_heartbeat_errors);
-                       if (carrier_changes)
-                               print_num(fp, 7,
-                                         rta_getattr_u32(carrier_changes));
-               }
-       }
-}
-
-static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
-                              const struct rtattr *carrier_changes)
-{
-       if (is_json_context()) {
-               open_json_object("stats");
-
-               /* RX stats */
-               open_json_object("rx");
-               print_uint(PRINT_JSON, "bytes", NULL, s->rx_bytes);
-               print_uint(PRINT_JSON, "packets", NULL, s->rx_packets);
-               print_uint(PRINT_JSON, "errors", NULL, s->rx_errors);
-               print_uint(PRINT_JSON, "dropped", NULL, s->rx_dropped);
-               print_uint(PRINT_JSON, "over_errors", NULL, s->rx_over_errors);
-               print_uint(PRINT_JSON, "multicast", NULL, s->multicast);
-               if (s->rx_compressed)
-                       print_int(PRINT_JSON,
-                                 "compressed",
-                                 NULL, s->rx_compressed);
-
-               /* RX error stats */
-               if (show_stats > 1) {
-                       print_uint(PRINT_JSON,
-                                  "length_errors",
-                                  NULL, s->rx_length_errors);
-                       print_uint(PRINT_JSON,
-                                  "crc_errors",
-                                  NULL, s->rx_crc_errors);
-                       print_uint(PRINT_JSON,
-                                  "frame_errors",
-                                  NULL, s->rx_frame_errors);
-                       print_uint(PRINT_JSON,
-                                  "fifo_errors",
-                                  NULL, s->rx_fifo_errors);
-                       print_uint(PRINT_JSON,
-                                  "missed_errors",
-                                  NULL, s->rx_missed_errors);
-                       if (s->rx_nohandler)
-                               print_int(PRINT_JSON,
-                                         "nohandler",
-                                         NULL, s->rx_nohandler);
-               }
-               close_json_object();
-
-               /* TX stats */
-               open_json_object("tx");
-               print_uint(PRINT_JSON, "bytes", NULL, s->tx_bytes);
-               print_uint(PRINT_JSON, "packets", NULL, s->tx_packets);
-               print_uint(PRINT_JSON, "errors", NULL, s->tx_errors);
-               print_uint(PRINT_JSON, "dropped", NULL, s->tx_dropped);
-               print_uint(PRINT_JSON,
-                          "carrier_errors",
-                          NULL, s->tx_carrier_errors);
-               print_uint(PRINT_JSON, "collisions", NULL, s->collisions);
-               if (s->tx_compressed)
-                       print_int(PRINT_JSON,
-                                 "compressed",
-                                 NULL, s->tx_compressed);
-
-               /* TX error stats */
-               if (show_stats > 1) {
-                       print_uint(PRINT_JSON,
-                                  "aborted_errors",
-                                  NULL, s->tx_aborted_errors);
-                       print_uint(PRINT_JSON,
-                                  "fifo_errors",
-                                  NULL, s->tx_fifo_errors);
-                       print_uint(PRINT_JSON,
-                                  "window_errors",
-                                  NULL, s->tx_window_errors);
-                       print_uint(PRINT_JSON,
-                                  "heartbeat_errors",
-                                  NULL, s->tx_heartbeat_errors);
-                       if (carrier_changes)
-                               print_uint(PRINT_JSON,
-                                          "carrier_changes",
-                                          NULL,
-                                          rta_getattr_u32(carrier_changes));
-               }
 
                close_json_object();
                close_json_object();
@@ -825,7 +681,6 @@ static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
                fprintf(fp, "    RX: bytes  packets  errors  dropped overrun mcast   %s%s",
                        s->rx_compressed ? "compressed" : "", _SL_);
 
-
                fprintf(fp, "    ");
                print_num(fp, 10, s->rx_bytes);
                print_num(fp, 8, s->rx_packets);
@@ -886,27 +741,6 @@ static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
        }
 }
 
-static void __print_link_stats(FILE *fp, struct rtattr **tb)
-{
-       const struct rtattr *carrier_changes = tb[IFLA_CARRIER_CHANGES];
-
-       if (tb[IFLA_STATS64]) {
-               struct rtnl_link_stats64 stats = { 0 };
-
-               memcpy(&stats, RTA_DATA(tb[IFLA_STATS64]),
-                      MIN(RTA_PAYLOAD(tb[IFLA_STATS64]), sizeof(stats)));
-
-               print_link_stats64(fp, &stats, carrier_changes);
-       } else if (tb[IFLA_STATS]) {
-               struct rtnl_link_stats stats = { 0 };
-
-               memcpy(&stats, RTA_DATA(tb[IFLA_STATS]),
-                      MIN(RTA_PAYLOAD(tb[IFLA_STATS]), sizeof(stats)));
-
-               print_link_stats32(fp, &stats, carrier_changes);
-       }
-}
-
 static void print_link_stats(FILE *fp, struct nlmsghdr *n)
 {
        struct ifinfomsg *ifi = NLMSG_DATA(n);
@@ -918,95 +752,18 @@ static void print_link_stats(FILE *fp, struct nlmsghdr *n)
        fprintf(fp, "%s", _SL_);
 }
 
-int print_linkinfo_brief(const struct sockaddr_nl *who,
-                        struct nlmsghdr *n, void *arg,
-                        struct link_filter *pfilter)
+static int print_linkinfo_brief(FILE *fp, const char *name,
+                               const struct ifinfomsg *ifi,
+                               struct rtattr *tb[])
 {
-       FILE *fp = (FILE *)arg;
-       struct ifinfomsg *ifi = NLMSG_DATA(n);
-       struct rtattr *tb[IFLA_MAX+1];
-       int len = n->nlmsg_len;
-       const char *name;
-       char buf[32] = { 0, };
        unsigned int m_flag = 0;
 
-       if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
-               return -1;
-
-       len -= NLMSG_LENGTH(sizeof(*ifi));
-       if (len < 0)
-               return -1;
-
-       if (!pfilter)
-               pfilter = &filter;
-
-       if (pfilter->ifindex && ifi->ifi_index != pfilter->ifindex)
-               return -1;
-       if (pfilter->up && !(ifi->ifi_flags&IFF_UP))
-               return -1;
-
-       parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
-       if (tb[IFLA_IFNAME] == NULL) {
-               fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
-               name = "<nil>";
-       } else {
-               name = rta_getattr_str(tb[IFLA_IFNAME]);
-       }
-
-       if (pfilter->label &&
-           (!pfilter->family || pfilter->family == AF_PACKET) &&
-           fnmatch(pfilter->label, RTA_DATA(tb[IFLA_IFNAME]), 0))
-               return -1;
-
-       if (tb[IFLA_GROUP]) {
-               int group = rta_getattr_u32(tb[IFLA_GROUP]);
-
-               if (pfilter->group != -1 && group != pfilter->group)
-                       return -1;
-       }
-
-       if (tb[IFLA_MASTER]) {
-               int master = rta_getattr_u32(tb[IFLA_MASTER]);
-
-               if (pfilter->master > 0 && master != pfilter->master)
-                       return -1;
-       } else if (pfilter->master > 0)
-               return -1;
-
-       if (pfilter->kind && match_link_kind(tb, pfilter->kind, 0))
-               return -1;
-
-       if (pfilter->slave_kind && match_link_kind(tb, pfilter->slave_kind, 1))
-               return -1;
-
-       if (n->nlmsg_type == RTM_DELLINK)
-               print_bool(PRINT_ANY, "deleted", "Deleted ", true);
-
-       if (tb[IFLA_LINK]) {
-               SPRINT_BUF(b1);
-               int iflink = rta_getattr_u32(tb[IFLA_LINK]);
-
-               if (iflink == 0) {
-                       snprintf(buf, sizeof(buf), "%s@NONE", name);
-                       print_null(PRINT_JSON, "link", NULL, NULL);
-               } else {
-                       const char *link = ll_idx_n2a(iflink, b1);
-
-                       print_string(PRINT_JSON, "link", NULL, link);
-                       snprintf(buf, sizeof(buf), "%s@%s", name, link);
-                       m_flag = ll_index_to_flags(iflink);
-                       m_flag = !(m_flag & IFF_UP);
-               }
-       } else
-               snprintf(buf, sizeof(buf), "%s", name);
-
-       print_string(PRINT_FP, NULL, "%-16s ", buf);
-       print_string(PRINT_JSON, "ifname", NULL, name);
+       m_flag = print_name_and_link("%-16s ", name, tb);
 
        if (tb[IFLA_OPERSTATE])
                print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE]));
 
-       if (pfilter->family == AF_PACKET) {
+       if (filter.family == AF_PACKET) {
                SPRINT_BUF(b1);
 
                if (tb[IFLA_ADDRESS]) {
@@ -1020,10 +777,11 @@ int print_linkinfo_brief(const struct sockaddr_nl *who,
                }
        }
 
-       if (pfilter->family == AF_PACKET) {
+       if (filter.family == AF_PACKET) {
                print_link_flags(fp, ifi->ifi_flags, m_flag);
                print_string(PRINT_FP, NULL, "%s", "\n");
        }
+
        fflush(fp);
        return 0;
 }
@@ -1057,7 +815,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
        struct ifinfomsg *ifi = NLMSG_DATA(n);
        struct rtattr *tb[IFLA_MAX+1];
        int len = n->nlmsg_len;
+       const char *name;
        unsigned int m_flag = 0;
+       SPRINT_BUF(b1);
 
        if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK)
                return 0;
@@ -1067,18 +827,20 @@ int print_linkinfo(const struct sockaddr_nl *who,
                return -1;
 
        if (filter.ifindex && ifi->ifi_index != filter.ifindex)
-               return 0;
+               return -1;
        if (filter.up && !(ifi->ifi_flags&IFF_UP))
-               return 0;
+               return -1;
 
        parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
-       if (tb[IFLA_IFNAME] == NULL)
-               fprintf(stderr, "BUG: device with ifindex %d has nil ifname\n", ifi->ifi_index);
+
+       name = get_ifname_rta(ifi->ifi_index, tb[IFLA_IFNAME]);
+       if (!name)
+               return -1;
 
        if (filter.label &&
            (!filter.family || filter.family == AF_PACKET) &&
-           fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
-               return 0;
+           fnmatch(filter.label, name, 0))
+               return -1;
 
        if (tb[IFLA_GROUP]) {
                int group = rta_getattr_u32(tb[IFLA_GROUP]);
@@ -1104,41 +866,12 @@ int print_linkinfo(const struct sockaddr_nl *who,
        if (n->nlmsg_type == RTM_DELLINK)
                print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 
-       print_int(PRINT_ANY, "ifindex", "%d: ", ifi->ifi_index);
-       if (tb[IFLA_IFNAME]) {
-               print_color_string(PRINT_ANY,
-                                  COLOR_IFNAME,
-                                  "ifname", "%s",
-                                  rta_getattr_str(tb[IFLA_IFNAME]));
-       } else {
-               print_null(PRINT_JSON, "ifname", NULL, NULL);
-               print_color_null(PRINT_FP, COLOR_IFNAME,
-                                "ifname", "%s", "<nil>");
-       }
-
-       if (tb[IFLA_LINK]) {
-               int iflink = rta_getattr_u32(tb[IFLA_LINK]);
+       if (brief)
+               return print_linkinfo_brief(fp, name, ifi, tb);
 
-               if (iflink == 0)
-                       print_null(PRINT_ANY, "link", "@%s: ", "NONE");
-               else {
-                       if (tb[IFLA_LINK_NETNSID])
-                               print_int(PRINT_ANY,
-                                         "link_index", "@if%d: ", iflink);
-                       else {
-                               SPRINT_BUF(b1);
+       print_int(PRINT_ANY, "ifindex", "%d: ", ifi->ifi_index);
 
-                               print_string(PRINT_ANY,
-                                            "link",
-                                            "@%s: ",
-                                            ll_idx_n2a(iflink, b1));
-                               m_flag = ll_index_to_flags(iflink);
-                               m_flag = !(m_flag & IFF_UP);
-                       }
-               }
-       } else {
-               print_string(PRINT_FP, NULL, ": ", NULL);
-       }
+       m_flag = print_name_and_link("%s: ", name, tb);
        print_link_flags(fp, ifi->ifi_flags, m_flag);
 
        if (tb[IFLA_MTU])
@@ -1153,12 +886,11 @@ int print_linkinfo(const struct sockaddr_nl *who,
                             "qdisc %s ",
                             rta_getattr_str(tb[IFLA_QDISC]));
        if (tb[IFLA_MASTER]) {
-               SPRINT_BUF(b1);
+               int master = rta_getattr_u32(tb[IFLA_MASTER]);
 
                print_string(PRINT_ANY,
-                            "master",
-                            "master %s ",
-                            ll_idx_n2a(rta_getattr_u32(tb[IFLA_MASTER]), b1));
+                            "master", "master %s ",
+                            ll_index_to_name(master));
        }
 
        if (tb[IFLA_OPERSTATE])
@@ -1168,7 +900,6 @@ int print_linkinfo(const struct sockaddr_nl *who,
                print_linkmode(fp, tb[IFLA_LINKMODE]);
 
        if (tb[IFLA_GROUP]) {
-               SPRINT_BUF(b1);
                int group = rta_getattr_u32(tb[IFLA_GROUP]);
 
                print_string(PRINT_ANY,
@@ -1184,8 +915,6 @@ int print_linkinfo(const struct sockaddr_nl *who,
                print_link_event(fp, rta_getattr_u32(tb[IFLA_EVENT]));
 
        if (!filter.family || filter.family == AF_PACKET || show_details) {
-               SPRINT_BUF(b1);
-
                print_string(PRINT_FP, NULL, "%s", _SL_);
                print_string(PRINT_ANY,
                             "link_type",
@@ -1285,7 +1014,6 @@ int print_linkinfo(const struct sockaddr_nl *who,
                                     rta_getattr_str(tb[IFLA_PHYS_PORT_NAME]));
 
                if (tb[IFLA_PHYS_PORT_ID]) {
-                       SPRINT_BUF(b1);
                        print_string(PRINT_ANY,
                                     "phys_port_id",
                                     "portid %s ",
@@ -1296,7 +1024,6 @@ int print_linkinfo(const struct sockaddr_nl *who,
                }
 
                if (tb[IFLA_PHYS_SWITCH_ID]) {
-                       SPRINT_BUF(b1);
                        print_string(PRINT_ANY,
                                     "phys_switch_id",
                                     "switchid %s ",
@@ -1335,7 +1062,7 @@ int print_linkinfo(const struct sockaddr_nl *who,
                close_json_array(PRINT_JSON, NULL);
        }
 
-       print_string(PRINT_FP, NULL, "\n", NULL);
+       print_string(PRINT_FP, NULL, "%s", "\n");
        fflush(fp);
        return 1;
 }
@@ -1474,6 +1201,21 @@ static int get_filter(const char *arg)
        return 0;
 }
 
+static int ifa_label_match_rta(int ifindex, const struct rtattr *rta)
+{
+       const char *label;
+
+       if (!filter.label)
+               return 0;
+
+       if (rta)
+               label = RTA_DATA(rta);
+       else
+               label = ll_index_to_name(ifindex);
+
+       return fnmatch(filter.label, label, 0);
+}
+
 int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
                   void *arg)
 {
@@ -1512,21 +1254,13 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
                return 0;
        if ((filter.flags ^ ifa_flags) & filter.flagmask)
                return 0;
-       if (filter.label) {
-               SPRINT_BUF(b1);
-               const char *label;
-
-               if (rta_tb[IFA_LABEL])
-                       label = RTA_DATA(rta_tb[IFA_LABEL]);
-               else
-                       label = ll_idx_n2a(ifa->ifa_index, b1);
-               if (fnmatch(filter.label, label, 0) != 0)
-                       return 0;
-       }
 
        if (filter.family && filter.family != ifa->ifa_family)
                return 0;
 
+       if (ifa_label_match_rta(ifa->ifa_index, rta_tb[IFA_LABEL]))
+               return 0;
+
        if (inet_addr_match_rta(&filter.pfx, rta_tb[IFA_LOCAL]))
                return 0;
 
@@ -1882,25 +1616,14 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
 
                        if ((filter.flags ^ ifa_flags) & filter.flagmask)
                                continue;
-                       if (filter.pfx.family || filter.label) {
-                               struct rtattr *rta =
-                                       tb[IFA_LOCAL] ? : tb[IFA_ADDRESS];
-
-                               if (inet_addr_match_rta(&filter.pfx, rta))
-                                       continue;
-
-                               if (filter.label) {
-                                       SPRINT_BUF(b1);
-                                       const char *label;
-
-                                       if (tb[IFA_LABEL])
-                                               label = RTA_DATA(tb[IFA_LABEL]);
-                                       else
-                                               label = ll_idx_n2a(ifa->ifa_index, b1);
-                                       if (fnmatch(filter.label, label, 0) != 0)
-                                               continue;
-                               }
-                       }
+
+                       if (ifa_label_match_rta(ifa->ifa_index, tb[IFA_LABEL]))
+                               continue;
+
+                       if (!tb[IFA_LOCAL])
+                               tb[IFA_LOCAL] = tb[IFA_ADDRESS];
+                       if (inet_addr_match_rta(&filter.pfx, tb[IFA_LOCAL]))
+                               continue;
 
                        ok = 1;
                        break;
@@ -2192,25 +1915,17 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
                ipaddr_filter(&linfo, ainfo);
 
        for (l = linfo.head; l; l = l->next) {
+               struct nlmsghdr *n = &l->h;
+               struct ifinfomsg *ifi = NLMSG_DATA(n);
                int res = 0;
-               struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
 
                open_json_object(NULL);
-               if (brief) {
-                       if (print_linkinfo_brief(NULL, &l->h,
-                                                stdout, NULL) == 0)
-                               if (filter.family != AF_PACKET)
-                                       print_selected_addrinfo(ifi,
-                                                               ainfo->head,
-                                                               stdout);
-               } else if (no_link ||
-                          (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) {
-                       if (filter.family != AF_PACKET)
-                               print_selected_addrinfo(ifi,
-                                                       ainfo->head, stdout);
-                       if (res > 0 && !do_link && show_stats)
-                               print_link_stats(stdout, &l->h);
-               }
+               if (brief || !no_link)
+                       res = print_linkinfo(NULL, n, stdout);
+               if (res >= 0 && filter.family != AF_PACKET)
+                       print_selected_addrinfo(ifi, ainfo->head, stdout);
+               if (res > 0 && !do_link && show_stats)
+                       print_link_stats(stdout, n);
                close_json_object();
        }
        fflush(stdout);
@@ -2496,10 +2211,9 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
        if (!scoped && cmd != RTM_DELADDR)
                req.ifa.ifa_scope = default_scope(&lcl);
 
-       if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) {
-               fprintf(stderr, "Cannot find device \"%s\"\n", d);
-               return -1;
-       }
+       req.ifa.ifa_index = ll_name_to_index(d);
+       if (!req.ifa.ifa_index)
+               return nodev(d);
 
        if (valid_lftp || preferred_lftp) {
                struct ifa_cacheinfo cinfo = {};