inet6.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * lib/route/link/inet6.c AF_INET6 link operations
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  10. */
  11. #include <netlink-private/netlink.h>
  12. #include <netlink/netlink.h>
  13. #include <netlink/attr.h>
  14. #include <netlink/route/rtnl.h>
  15. #include <netlink-private/route/link/api.h>
  16. struct inet6_data
  17. {
  18. uint32_t i6_flags;
  19. struct ifla_cacheinfo i6_cacheinfo;
  20. uint32_t i6_conf[DEVCONF_MAX];
  21. };
  22. static void *inet6_alloc(struct rtnl_link *link)
  23. {
  24. return calloc(1, sizeof(struct inet6_data));
  25. }
  26. static void *inet6_clone(struct rtnl_link *link, void *data)
  27. {
  28. struct inet6_data *i6;
  29. if ((i6 = inet6_alloc(link)))
  30. memcpy(i6, data, sizeof(*i6));
  31. return i6;
  32. }
  33. static void inet6_free(struct rtnl_link *link, void *data)
  34. {
  35. free(data);
  36. }
  37. static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
  38. [IFLA_INET6_FLAGS] = { .type = NLA_U32 },
  39. [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) },
  40. [IFLA_INET6_CONF] = { .minlen = 4 },
  41. [IFLA_INET6_STATS] = { .minlen = 8 },
  42. [IFLA_INET6_ICMP6STATS] = { .minlen = 8 },
  43. };
  44. static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = {
  45. /* 14a196807482e6fc74f15fc03176d5c08880588f^:include/linux/snmp.h
  46. * version before the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f.
  47. * This version was valid since commit edf391ff17232f097d72441c9ad467bcb3b5db18, which
  48. * predates support for parsing IFLA_PROTINFO in libnl3. Such an even older meaning of
  49. * the flags is not supported in libnl3. */
  50. [ 1] = RTNL_LINK_IP6_INPKTS, /* IPSTATS_MIB_INPKTS */
  51. [ 2] = RTNL_LINK_IP6_INHDRERRORS, /* IPSTATS_MIB_INHDRERRORS */
  52. [ 3] = RTNL_LINK_IP6_INTOOBIGERRORS, /* IPSTATS_MIB_INTOOBIGERRORS */
  53. [ 4] = RTNL_LINK_IP6_INNOROUTES, /* IPSTATS_MIB_INNOROUTES */
  54. [ 5] = RTNL_LINK_IP6_INADDRERRORS, /* IPSTATS_MIB_INADDRERRORS */
  55. [ 6] = RTNL_LINK_IP6_INUNKNOWNPROTOS, /* IPSTATS_MIB_INUNKNOWNPROTOS */
  56. [ 7] = RTNL_LINK_IP6_INTRUNCATEDPKTS, /* IPSTATS_MIB_INTRUNCATEDPKTS */
  57. [ 8] = RTNL_LINK_IP6_INDISCARDS, /* IPSTATS_MIB_INDISCARDS */
  58. [ 9] = RTNL_LINK_IP6_INDELIVERS, /* IPSTATS_MIB_INDELIVERS */
  59. [10] = RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* IPSTATS_MIB_OUTFORWDATAGRAMS */
  60. [11] = RTNL_LINK_IP6_OUTPKTS, /* IPSTATS_MIB_OUTPKTS */
  61. [12] = RTNL_LINK_IP6_OUTDISCARDS, /* IPSTATS_MIB_OUTDISCARDS */
  62. [13] = RTNL_LINK_IP6_OUTNOROUTES, /* IPSTATS_MIB_OUTNOROUTES */
  63. [14] = RTNL_LINK_IP6_REASMTIMEOUT, /* IPSTATS_MIB_REASMTIMEOUT */
  64. [15] = RTNL_LINK_IP6_REASMREQDS, /* IPSTATS_MIB_REASMREQDS */
  65. [16] = RTNL_LINK_IP6_REASMOKS, /* IPSTATS_MIB_REASMOKS */
  66. [17] = RTNL_LINK_IP6_REASMFAILS, /* IPSTATS_MIB_REASMFAILS */
  67. [18] = RTNL_LINK_IP6_FRAGOKS, /* IPSTATS_MIB_FRAGOKS */
  68. [19] = RTNL_LINK_IP6_FRAGFAILS, /* IPSTATS_MIB_FRAGFAILS */
  69. [20] = RTNL_LINK_IP6_FRAGCREATES, /* IPSTATS_MIB_FRAGCREATES */
  70. [21] = RTNL_LINK_IP6_INMCASTPKTS, /* IPSTATS_MIB_INMCASTPKTS */
  71. [22] = RTNL_LINK_IP6_OUTMCASTPKTS, /* IPSTATS_MIB_OUTMCASTPKTS */
  72. [23] = RTNL_LINK_IP6_INBCASTPKTS, /* IPSTATS_MIB_INBCASTPKTS */
  73. [24] = RTNL_LINK_IP6_OUTBCASTPKTS, /* IPSTATS_MIB_OUTBCASTPKTS */
  74. [25] = RTNL_LINK_IP6_INOCTETS, /* IPSTATS_MIB_INOCTETS */
  75. [26] = RTNL_LINK_IP6_OUTOCTETS, /* IPSTATS_MIB_OUTOCTETS */
  76. [27] = RTNL_LINK_IP6_INMCASTOCTETS, /* IPSTATS_MIB_INMCASTOCTETS */
  77. [28] = RTNL_LINK_IP6_OUTMCASTOCTETS, /* IPSTATS_MIB_OUTMCASTOCTETS */
  78. [29] = RTNL_LINK_IP6_INBCASTOCTETS, /* IPSTATS_MIB_INBCASTOCTETS */
  79. [30] = RTNL_LINK_IP6_OUTBCASTOCTETS, /* IPSTATS_MIB_OUTBCASTOCTETS */
  80. };
  81. static const uint8_t map_stat_id_from_IPSTATS_MIB_v2[__IPSTATS_MIB_MAX] = {
  82. /* d8ec26d7f8287f5788a494f56e8814210f0e64be:include/uapi/linux/snmp.h
  83. * version since the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f */
  84. [ 1] = RTNL_LINK_IP6_INPKTS, /* IPSTATS_MIB_INPKTS */
  85. [ 2] = RTNL_LINK_IP6_INOCTETS, /* IPSTATS_MIB_INOCTETS */
  86. [ 3] = RTNL_LINK_IP6_INDELIVERS, /* IPSTATS_MIB_INDELIVERS */
  87. [ 4] = RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* IPSTATS_MIB_OUTFORWDATAGRAMS */
  88. [ 5] = RTNL_LINK_IP6_OUTPKTS, /* IPSTATS_MIB_OUTPKTS */
  89. [ 6] = RTNL_LINK_IP6_OUTOCTETS, /* IPSTATS_MIB_OUTOCTETS */
  90. [ 7] = RTNL_LINK_IP6_INHDRERRORS, /* IPSTATS_MIB_INHDRERRORS */
  91. [ 8] = RTNL_LINK_IP6_INTOOBIGERRORS, /* IPSTATS_MIB_INTOOBIGERRORS */
  92. [ 9] = RTNL_LINK_IP6_INNOROUTES, /* IPSTATS_MIB_INNOROUTES */
  93. [10] = RTNL_LINK_IP6_INADDRERRORS, /* IPSTATS_MIB_INADDRERRORS */
  94. [11] = RTNL_LINK_IP6_INUNKNOWNPROTOS, /* IPSTATS_MIB_INUNKNOWNPROTOS */
  95. [12] = RTNL_LINK_IP6_INTRUNCATEDPKTS, /* IPSTATS_MIB_INTRUNCATEDPKTS */
  96. [13] = RTNL_LINK_IP6_INDISCARDS, /* IPSTATS_MIB_INDISCARDS */
  97. [14] = RTNL_LINK_IP6_OUTDISCARDS, /* IPSTATS_MIB_OUTDISCARDS */
  98. [15] = RTNL_LINK_IP6_OUTNOROUTES, /* IPSTATS_MIB_OUTNOROUTES */
  99. [16] = RTNL_LINK_IP6_REASMTIMEOUT, /* IPSTATS_MIB_REASMTIMEOUT */
  100. [17] = RTNL_LINK_IP6_REASMREQDS, /* IPSTATS_MIB_REASMREQDS */
  101. [18] = RTNL_LINK_IP6_REASMOKS, /* IPSTATS_MIB_REASMOKS */
  102. [19] = RTNL_LINK_IP6_REASMFAILS, /* IPSTATS_MIB_REASMFAILS */
  103. [20] = RTNL_LINK_IP6_FRAGOKS, /* IPSTATS_MIB_FRAGOKS */
  104. [21] = RTNL_LINK_IP6_FRAGFAILS, /* IPSTATS_MIB_FRAGFAILS */
  105. [22] = RTNL_LINK_IP6_FRAGCREATES, /* IPSTATS_MIB_FRAGCREATES */
  106. [23] = RTNL_LINK_IP6_INMCASTPKTS, /* IPSTATS_MIB_INMCASTPKTS */
  107. [24] = RTNL_LINK_IP6_OUTMCASTPKTS, /* IPSTATS_MIB_OUTMCASTPKTS */
  108. [25] = RTNL_LINK_IP6_INBCASTPKTS, /* IPSTATS_MIB_INBCASTPKTS */
  109. [26] = RTNL_LINK_IP6_OUTBCASTPKTS, /* IPSTATS_MIB_OUTBCASTPKTS */
  110. [27] = RTNL_LINK_IP6_INMCASTOCTETS, /* IPSTATS_MIB_INMCASTOCTETS */
  111. [28] = RTNL_LINK_IP6_OUTMCASTOCTETS, /* IPSTATS_MIB_OUTMCASTOCTETS */
  112. [29] = RTNL_LINK_IP6_INBCASTOCTETS, /* IPSTATS_MIB_INBCASTOCTETS */
  113. [30] = RTNL_LINK_IP6_OUTBCASTOCTETS, /* IPSTATS_MIB_OUTBCASTOCTETS */
  114. [31] = RTNL_LINK_IP6_CSUMERRORS, /* IPSTATS_MIB_CSUMERRORS */
  115. [32] = RTNL_LINK_IP6_NOECTPKTS, /* IPSTATS_MIB_NOECTPKTS */
  116. [33] = RTNL_LINK_IP6_ECT1PKTS, /* IPSTATS_MIB_ECT1PKTS */
  117. [34] = RTNL_LINK_IP6_ECT0PKTS, /* IPSTATS_MIB_ECT0PKTS */
  118. [35] = RTNL_LINK_IP6_CEPKTS, /* IPSTATS_MIB_CEPKTS */
  119. };
  120. static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
  121. void *data)
  122. {
  123. struct inet6_data *i6 = data;
  124. struct nlattr *tb[IFLA_INET6_MAX+1];
  125. int err;
  126. err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy);
  127. if (err < 0)
  128. return err;
  129. if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4)
  130. return -EINVAL;
  131. if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8)
  132. return -EINVAL;
  133. if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8)
  134. return -EINVAL;
  135. if (tb[IFLA_INET6_FLAGS])
  136. i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]);
  137. if (tb[IFLA_INET6_CACHEINFO])
  138. nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
  139. sizeof(i6->i6_cacheinfo));
  140. if (tb[IFLA_INET6_CONF])
  141. nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
  142. sizeof(i6->i6_conf));
  143. /*
  144. * Due to 32bit data alignment, these addresses must be copied to an
  145. * aligned location prior to access.
  146. */
  147. if (tb[IFLA_INET6_STATS]) {
  148. unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]);
  149. uint64_t stat;
  150. int i;
  151. int len = nla_len(tb[IFLA_INET6_STATS]) / 8;
  152. const uint8_t *map_stat_id = map_stat_id_from_IPSTATS_MIB_v2;
  153. if (len < 32 ||
  154. (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) < 6)) {
  155. /* kernel commit 14a196807482e6fc74f15fc03176d5c08880588f reordered the values.
  156. * The later commit 6a5dc9e598fe90160fee7de098fa319665f5253e added values
  157. * IPSTATS_MIB_CSUMERRORS/ICMP6_MIB_CSUMERRORS. If the netlink is shorter
  158. * then this, assume that the kernel uses the previous meaning of the
  159. * enumeration. */
  160. map_stat_id = map_stat_id_from_IPSTATS_MIB_v1;
  161. }
  162. len = min_t(int, __IPSTATS_MIB_MAX, len);
  163. for (i = 1; i < len; i++) {
  164. memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
  165. rtnl_link_set_stat(link, map_stat_id[i], stat);
  166. }
  167. }
  168. if (tb[IFLA_INET6_ICMP6STATS]) {
  169. unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
  170. uint64_t stat;
  171. int i;
  172. int len = min_t(int, __ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
  173. for (i = 1; i < len; i++) {
  174. memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
  175. rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1,
  176. stat);
  177. }
  178. }
  179. return 0;
  180. }
  181. /* These live in include/net/if_inet6.h and should be moved to include/linux */
  182. #define IF_RA_OTHERCONF 0x80
  183. #define IF_RA_MANAGED 0x40
  184. #define IF_RA_RCVD 0x20
  185. #define IF_RS_SENT 0x10
  186. #define IF_READY 0x80000000
  187. static const struct trans_tbl inet6_flags[] = {
  188. __ADD(IF_RA_OTHERCONF, ra_otherconf)
  189. __ADD(IF_RA_MANAGED, ra_managed)
  190. __ADD(IF_RA_RCVD, ra_rcvd)
  191. __ADD(IF_RS_SENT, rs_sent)
  192. __ADD(IF_READY, ready)
  193. };
  194. static char *inet6_flags2str(int flags, char *buf, size_t len)
  195. {
  196. return __flags2str(flags, buf, len, inet6_flags,
  197. ARRAY_SIZE(inet6_flags));
  198. }
  199. static const struct trans_tbl inet6_devconf[] = {
  200. __ADD(DEVCONF_FORWARDING, forwarding)
  201. __ADD(DEVCONF_HOPLIMIT, hoplimit)
  202. __ADD(DEVCONF_MTU6, mtu6)
  203. __ADD(DEVCONF_ACCEPT_RA, accept_ra)
  204. __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects)
  205. __ADD(DEVCONF_AUTOCONF, autoconf)
  206. __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits)
  207. __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits)
  208. __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval)
  209. __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay)
  210. __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr)
  211. __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft)
  212. __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft)
  213. __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry)
  214. __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor)
  215. __ADD(DEVCONF_MAX_ADDRESSES, max_addresses)
  216. __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version)
  217. __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr)
  218. __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo)
  219. __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref)
  220. __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval)
  221. __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info)
  222. __ADD(DEVCONF_PROXY_NDP, proxy_ndp)
  223. __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad)
  224. __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route)
  225. __ADD(DEVCONF_MC_FORWARDING, mc_forwarding)
  226. __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6)
  227. __ADD(DEVCONF_ACCEPT_DAD, accept_dad)
  228. __ADD(DEVCONF_FORCE_TLLAO, force_tllao)
  229. };
  230. static char *inet6_devconf2str(int type, char *buf, size_t len)
  231. {
  232. return __type2str(type, buf, len, inet6_devconf,
  233. ARRAY_SIZE(inet6_devconf));
  234. }
  235. static void inet6_dump_details(struct rtnl_link *link,
  236. struct nl_dump_params *p, void *data)
  237. {
  238. struct inet6_data *i6 = data;
  239. char buf[64], buf2[64];
  240. int i, n = 0;
  241. nl_dump_line(p, " ipv6 max-reasm-len %s",
  242. nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf)));
  243. nl_dump(p, " <%s>\n",
  244. inet6_flags2str(i6->i6_flags, buf, sizeof(buf)));
  245. nl_dump_line(p, " create-stamp %.2fs reachable-time %s",
  246. (double) i6->i6_cacheinfo.tstamp / 100.,
  247. nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf)));
  248. nl_dump(p, " retrans-time %s\n",
  249. nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf)));
  250. nl_dump_line(p, " devconf:\n");
  251. nl_dump_line(p, " ");
  252. for (i = 0; i < DEVCONF_MAX; i++) {
  253. uint32_t value = i6->i6_conf[i];
  254. int x, offset;
  255. switch (i) {
  256. case DEVCONF_TEMP_VALID_LFT:
  257. case DEVCONF_TEMP_PREFERED_LFT:
  258. nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2));
  259. break;
  260. case DEVCONF_RTR_PROBE_INTERVAL:
  261. case DEVCONF_RTR_SOLICIT_INTERVAL:
  262. case DEVCONF_RTR_SOLICIT_DELAY:
  263. nl_msec2str(value, buf2, sizeof(buf2));
  264. break;
  265. default:
  266. snprintf(buf2, sizeof(buf2), "%u", value);
  267. break;
  268. }
  269. inet6_devconf2str(i, buf, sizeof(buf));
  270. offset = 23 - strlen(buf2);
  271. if (offset < 0)
  272. offset = 0;
  273. for (x = strlen(buf); x < offset; x++)
  274. buf[x] = ' ';
  275. strncpy(&buf[offset], buf2, strlen(buf2));
  276. nl_dump_line(p, "%s", buf);
  277. if (++n == 3) {
  278. nl_dump(p, "\n");
  279. nl_dump_line(p, " ");
  280. n = 0;
  281. } else
  282. nl_dump(p, " ");
  283. }
  284. if (n != 0)
  285. nl_dump(p, "\n");
  286. }
  287. static void inet6_dump_stats(struct rtnl_link *link,
  288. struct nl_dump_params *p, void *data)
  289. {
  290. double octets;
  291. char *octetsUnit;
  292. nl_dump(p, " IPv6: InPkts InOctets "
  293. " InDiscards InDelivers\n");
  294. nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INPKTS]);
  295. octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INOCTETS],
  296. &octetsUnit);
  297. if (octets)
  298. nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
  299. else
  300. nl_dump(p, "%16" PRIu64 " B ", 0);
  301. nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n",
  302. link->l_stats[RTNL_LINK_IP6_INDISCARDS],
  303. link->l_stats[RTNL_LINK_IP6_INDELIVERS]);
  304. nl_dump(p, " OutPkts OutOctets "
  305. " OutDiscards OutForwards\n");
  306. nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]);
  307. octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTOCTETS],
  308. &octetsUnit);
  309. if (octets)
  310. nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
  311. else
  312. nl_dump(p, "%16" PRIu64 " B ", 0);
  313. nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n",
  314. link->l_stats[RTNL_LINK_IP6_OUTDISCARDS],
  315. link->l_stats[RTNL_LINK_IP6_OUTFORWDATAGRAMS]);
  316. nl_dump(p, " InMcastPkts InMcastOctets "
  317. " InBcastPkts InBcastOctests\n");
  318. nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]);
  319. octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INMCASTOCTETS],
  320. &octetsUnit);
  321. if (octets)
  322. nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
  323. else
  324. nl_dump(p, "%16" PRIu64 " B ", 0);
  325. nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]);
  326. octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS],
  327. &octetsUnit);
  328. if (octets)
  329. nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
  330. else
  331. nl_dump(p, "%16" PRIu64 " B\n", 0);
  332. nl_dump(p, " OutMcastPkts OutMcastOctets "
  333. " OutBcastPkts OutBcastOctests\n");
  334. nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]);
  335. octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTMCASTOCTETS],
  336. &octetsUnit);
  337. if (octets)
  338. nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
  339. else
  340. nl_dump(p, "%16" PRIu64 " B ", 0);
  341. nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]);
  342. octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS],
  343. &octetsUnit);
  344. if (octets)
  345. nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
  346. else
  347. nl_dump(p, "%16" PRIu64 " B\n", 0);
  348. nl_dump(p, " ReasmOKs ReasmFails "
  349. " ReasmReqds ReasmTimeout\n");
  350. nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
  351. link->l_stats[RTNL_LINK_IP6_REASMOKS],
  352. link->l_stats[RTNL_LINK_IP6_REASMFAILS],
  353. link->l_stats[RTNL_LINK_IP6_REASMREQDS],
  354. link->l_stats[RTNL_LINK_IP6_REASMTIMEOUT]);
  355. nl_dump(p, " FragOKs FragFails "
  356. " FragCreates\n");
  357. nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
  358. link->l_stats[RTNL_LINK_IP6_FRAGOKS],
  359. link->l_stats[RTNL_LINK_IP6_FRAGFAILS],
  360. link->l_stats[RTNL_LINK_IP6_FRAGCREATES]);
  361. nl_dump(p, " InHdrErrors InTooBigErrors "
  362. " InNoRoutes InAddrErrors\n");
  363. nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
  364. link->l_stats[RTNL_LINK_IP6_INHDRERRORS],
  365. link->l_stats[RTNL_LINK_IP6_INTOOBIGERRORS],
  366. link->l_stats[RTNL_LINK_IP6_INNOROUTES],
  367. link->l_stats[RTNL_LINK_IP6_INADDRERRORS]);
  368. nl_dump(p, " InUnknownProtos InTruncatedPkts "
  369. " OutNoRoutes InCsumErrors\n");
  370. nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
  371. link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS],
  372. link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS],
  373. link->l_stats[RTNL_LINK_IP6_OUTNOROUTES],
  374. link->l_stats[RTNL_LINK_IP6_CSUMERRORS]);
  375. nl_dump(p, " InNoECTPkts InECT1Pkts "
  376. " InECT0Pkts InCEPkts\n");
  377. nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
  378. link->l_stats[RTNL_LINK_IP6_NOECTPKTS],
  379. link->l_stats[RTNL_LINK_IP6_ECT1PKTS],
  380. link->l_stats[RTNL_LINK_IP6_ECT0PKTS],
  381. link->l_stats[RTNL_LINK_IP6_CEPKTS]);
  382. nl_dump(p, " ICMPv6: InMsgs InErrors "
  383. " OutMsgs OutErrors InCsumErrors\n");
  384. nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
  385. link->l_stats[RTNL_LINK_ICMP6_INMSGS],
  386. link->l_stats[RTNL_LINK_ICMP6_INERRORS],
  387. link->l_stats[RTNL_LINK_ICMP6_OUTMSGS],
  388. link->l_stats[RTNL_LINK_ICMP6_OUTERRORS],
  389. link->l_stats[RTNL_LINK_ICMP6_CSUMERRORS]);
  390. }
  391. static const struct nla_policy protinfo_policy = {
  392. .type = NLA_NESTED,
  393. };
  394. static struct rtnl_link_af_ops inet6_ops = {
  395. .ao_family = AF_INET6,
  396. .ao_alloc = &inet6_alloc,
  397. .ao_clone = &inet6_clone,
  398. .ao_free = &inet6_free,
  399. .ao_parse_protinfo = &inet6_parse_protinfo,
  400. .ao_parse_af = &inet6_parse_protinfo,
  401. .ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details,
  402. .ao_dump[NL_DUMP_STATS] = &inet6_dump_stats,
  403. .ao_protinfo_policy = &protinfo_policy,
  404. };
  405. static void __init inet6_init(void)
  406. {
  407. rtnl_link_af_register(&inet6_ops);
  408. }
  409. static void __exit inet6_exit(void)
  410. {
  411. rtnl_link_af_unregister(&inet6_ops);
  412. }