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