@@ -386,6 +386,126 @@ static void print_link_stats(FILE *fp, const struct rtnl_link_stats *s)
}
}
+static const char *ipv4_devconf[] = {
+ "forwarding",
+ "mc forwarding",
+ "proxy arp",
+ "accept redirects",
+ "secure redirects",
+ "send redirects",
+ "shared media",
+ "rp filter",
+ "accept source route",
+ "bootp relay",
+ "log martians",
+ "tag",
+ "arpfilter",
+ "medium id",
+ "noxfrm",
+ "nopolicy",
+ "force igmp version",
+ "arp announce",
+ "arp ignore",
+ "promote secondaries",
+ "arp accept",
+ "arp notify",
+ "accept local",
+ "src vmark",
+ "proxy arp pvlan",
+ "route localnet",
+};
+
+static void print_inet_conf(FILE *fp, struct rtattr *ininfo)
+{
+ struct rtattr *rta, *tb[IFLA_INET_MAX+1];
+
+ parse_rtattr_nested(tb, IFLA_INET_MAX, ininfo);
+
+ if ((rta = tb[IFLA_INET_CONF])) {
+ const __u32 *conf = (__u32 *)RTA_DATA(rta);
+ unsigned i;
+
+ fprintf(fp, "\n ipv4 conf:");
+ for (i = 0; i < rta->rta_len && i < ARRAY_SIZE(ipv4_devconf); i++) {
+ if (conf[i] != 0)
+ fprintf(fp, "\n %s:%u",
+ ipv4_devconf[i], conf[i]);
+ }
+ }
+}
+
+static const char *ipv6_devconf[] = {
+ "forwarding",
+ "hoplimit",
+ "mtu6",
+ "accept ra",
+ "accept redirects",
+ "autoconf",
+ "dad transmits",
+ "rtr solicits",
+ "rtr solicit interval",
+ "rtr solicit delay",
+ "use tempaddr",
+ "temp valid lft",
+ "temp prefered lft",
+ "regen max retry",
+ "max desync factor",
+ "max addresses",
+ "force mld version",
+ "accept ra defrtr",
+ "accept ra pinfo",
+ "accept ra rtr pref",
+ "rtr probe interval",
+ "accept ra rt info max plen",
+ "proxy ndp",
+ "optimistic dad",
+ "accept source route",
+ "mc forwarding",
+ "disable ipv6",
+ "accept dad",
+ "force tllao",
+ "ndisc notify",
+};
+
+static void print_inet6_conf(FILE *fp, struct rtattr *in6info)
+{
+ struct rtattr *rta, *tb[IFLA_INET6_MAX+1];
+
+ parse_rtattr_nested(tb, IFLA_INET6_MAX, in6info);
+
+ if ((rta = tb[IFLA_INET6_CONF])) {
+ const __u32 *conf = (__u32 *)RTA_DATA(rta);
+ unsigned i;
+
+ fprintf(fp, "\n ipv6 conf:");
+ for (i = 0; i < rta->rta_len && i < ARRAY_SIZE(ipv6_devconf); i++) {
+ if (conf[i] != 0)
+ fprintf(fp, "\n %s:%u",
+ ipv6_devconf[i], conf[i]);
+ }
+ }
+}
+
+static void print_afinfo(FILE *fp, struct rtattr *afinfo)
+{
+ struct rtattr *tb[AF_MAX+1];
+
+ if (afinfo->rta_type != IFLA_AF_SPEC) {
+ fprintf(stderr, "BUG: rta type is %d\n", afinfo->rta_type);
+ return;
+ }
+
+ parse_rtattr_nested(tb, AF_MAX, afinfo);
+
+ if (tb[AF_INET] &&
+ (!filter.family || filter.family == AF_INET))
+ print_inet_conf(fp, tb[AF_INET]);
+
+ if (tb[AF_INET6] &&
+ (!filter.family || filter.family == AF_INET))
+ print_inet6_conf(fp, tb[AF_INET6]);
+}
+
int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
@@ -509,6 +629,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
print_link_stats(fp, RTA_DATA(tb[IFLA_STATS]));
}
+ if (show_details && tb[IFLA_AF_SPEC])
+ print_afinfo(fp, tb[IFLA_AF_SPEC]);
+
if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) {
struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
int rem = RTA_PAYLOAD(vflist);