00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <netlink-local.h>
00013 #include <netlink/netlink.h>
00014 #include <netlink/attr.h>
00015 #include <netlink/route/rtnl.h>
00016 #include <netlink/route/link/api.h>
00017
00018 struct inet6_data
00019 {
00020 uint32_t i6_flags;
00021 struct ifla_cacheinfo i6_cacheinfo;
00022 uint32_t i6_conf[DEVCONF_MAX];
00023 };
00024
00025 static void *inet6_alloc(struct rtnl_link *link)
00026 {
00027 return calloc(1, sizeof(struct inet6_data));
00028 }
00029
00030 static void *inet6_clone(struct rtnl_link *link, void *data)
00031 {
00032 struct inet6_data *i6;
00033
00034 if ((i6 = inet6_alloc(link)))
00035 memcpy(i6, data, sizeof(*i6));
00036
00037 return i6;
00038 }
00039
00040 static void inet6_free(struct rtnl_link *link, void *data)
00041 {
00042 free(data);
00043 }
00044
00045 static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
00046 [IFLA_INET6_FLAGS] = { .type = NLA_U32 },
00047 [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) },
00048 [IFLA_INET6_CONF] = { .minlen = DEVCONF_MAX * 4 },
00049 [IFLA_INET6_STATS] = { .minlen = __IPSTATS_MIB_MAX * 8 },
00050 [IFLA_INET6_ICMP6STATS] = { .minlen = __ICMP6_MIB_MAX * 8 },
00051 };
00052
00053 static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
00054 void *data)
00055 {
00056 struct inet6_data *i6 = data;
00057 struct nlattr *tb[IFLA_INET6_MAX+1];
00058 int err;
00059
00060 err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy);
00061 if (err < 0)
00062 return err;
00063
00064 if (tb[IFLA_INET6_FLAGS])
00065 i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]);
00066
00067 if (tb[IFLA_INET6_CACHEINFO])
00068 nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
00069 sizeof(i6->i6_cacheinfo));
00070
00071 if (tb[IFLA_INET6_CONF])
00072 nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
00073 sizeof(i6->i6_conf));
00074
00075
00076
00077
00078
00079 if (tb[IFLA_INET6_STATS]) {
00080 unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]);
00081 uint64_t stat;
00082 int i;
00083
00084 for (i = 1; i < __IPSTATS_MIB_MAX; i++) {
00085 memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
00086 rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1,
00087 stat);
00088 }
00089 }
00090
00091 if (tb[IFLA_INET6_ICMP6STATS]) {
00092 unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
00093 uint64_t stat;
00094 int i;
00095
00096 for (i = 1; i < __ICMP6_MIB_MAX; i++) {
00097 memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
00098 rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1,
00099 stat);
00100 }
00101 }
00102
00103 return 0;
00104 }
00105
00106
00107 #define IF_RA_OTHERCONF 0x80
00108 #define IF_RA_MANAGED 0x40
00109 #define IF_RA_RCVD 0x20
00110 #define IF_RS_SENT 0x10
00111 #define IF_READY 0x80000000
00112
00113 static const struct trans_tbl inet6_flags[] = {
00114 __ADD(IF_RA_OTHERCONF, ra_otherconf)
00115 __ADD(IF_RA_MANAGED, ra_managed)
00116 __ADD(IF_RA_RCVD, ra_rcvd)
00117 __ADD(IF_RS_SENT, rs_sent)
00118 __ADD(IF_READY, ready)
00119 };
00120
00121 static char *inet6_flags2str(int flags, char *buf, size_t len)
00122 {
00123 return __flags2str(flags, buf, len, inet6_flags,
00124 ARRAY_SIZE(inet6_flags));
00125 }
00126
00127 static const struct trans_tbl inet6_devconf[] = {
00128 __ADD(DEVCONF_FORWARDING, forwarding)
00129 __ADD(DEVCONF_HOPLIMIT, hoplimit)
00130 __ADD(DEVCONF_MTU6, mtu6)
00131 __ADD(DEVCONF_ACCEPT_RA, accept_ra)
00132 __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects)
00133 __ADD(DEVCONF_AUTOCONF, autoconf)
00134 __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits)
00135 __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits)
00136 __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval)
00137 __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay)
00138 __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr)
00139 __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft)
00140 __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft)
00141 __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry)
00142 __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor)
00143 __ADD(DEVCONF_MAX_ADDRESSES, max_addresses)
00144 __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version)
00145 __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr)
00146 __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo)
00147 __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref)
00148 __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval)
00149 __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info)
00150 __ADD(DEVCONF_PROXY_NDP, proxy_ndp)
00151 __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad)
00152 __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route)
00153 __ADD(DEVCONF_MC_FORWARDING, mc_forwarding)
00154 __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6)
00155 __ADD(DEVCONF_ACCEPT_DAD, accept_dad)
00156 __ADD(DEVCONF_FORCE_TLLAO, force_tllao)
00157 };
00158
00159 static char *inet6_devconf2str(int type, char *buf, size_t len)
00160 {
00161 return __type2str(type, buf, len, inet6_devconf,
00162 ARRAY_SIZE(inet6_devconf));
00163 }
00164
00165
00166 static void inet6_dump_details(struct rtnl_link *link,
00167 struct nl_dump_params *p, void *data)
00168 {
00169 struct inet6_data *i6 = data;
00170 char buf[64], buf2[64];
00171 int i, n = 0;
00172
00173 nl_dump_line(p, " ipv6 max-reasm-len %s",
00174 nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf)));
00175
00176 nl_dump(p, " <%s>\n",
00177 inet6_flags2str(i6->i6_flags, buf, sizeof(buf)));
00178
00179
00180 nl_dump_line(p, " create-stamp %.2fs reachable-time %s",
00181 (double) i6->i6_cacheinfo.tstamp / 100.,
00182 nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf)));
00183
00184 nl_dump(p, " retrans-time %s\n",
00185 nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf)));
00186
00187 nl_dump_line(p, " devconf:\n");
00188 nl_dump_line(p, " ");
00189
00190 for (i = 0; i < DEVCONF_MAX; i++) {
00191 uint32_t value = i6->i6_conf[i];
00192 int x, offset;
00193
00194 switch (i) {
00195 case DEVCONF_TEMP_VALID_LFT:
00196 case DEVCONF_TEMP_PREFERED_LFT:
00197 nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2));
00198 break;
00199
00200 case DEVCONF_RTR_PROBE_INTERVAL:
00201 case DEVCONF_RTR_SOLICIT_INTERVAL:
00202 case DEVCONF_RTR_SOLICIT_DELAY:
00203 nl_msec2str(value, buf2, sizeof(buf2));
00204 break;
00205
00206 default:
00207 snprintf(buf2, sizeof(buf2), "%u", value);
00208 break;
00209
00210 }
00211
00212 inet6_devconf2str(i, buf, sizeof(buf));
00213
00214 offset = 23 - strlen(buf2);
00215 if (offset < 0)
00216 offset = 0;
00217
00218 for (x = strlen(buf); x < offset; x++)
00219 buf[x] = ' ';
00220
00221 strncpy(&buf[offset], buf2, strlen(buf2));
00222
00223 nl_dump_line(p, "%s", buf);
00224
00225 if (++n == 3) {
00226 nl_dump(p, "\n");
00227 nl_dump_line(p, " ");
00228 n = 0;
00229 } else
00230 nl_dump(p, " ");
00231 }
00232
00233 if (n != 0)
00234 nl_dump(p, "\n");
00235 }
00236
00237 static void inet6_dump_stats(struct rtnl_link *link,
00238 struct nl_dump_params *p, void *data)
00239 {
00240 double octets;
00241 char *octetsUnit;
00242
00243 nl_dump(p, " IPv6: InPkts InOctets "
00244 " InDiscards InDelivers\n");
00245 nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_INPKTS]);
00246
00247 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INOCTETS],
00248 &octetsUnit);
00249 if (octets)
00250 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
00251 else
00252 nl_dump(p, "%16llu B ", 0);
00253
00254 nl_dump(p, "%18llu %18llu\n",
00255 link->l_stats[RTNL_LINK_IP6_INDISCARDS],
00256 link->l_stats[RTNL_LINK_IP6_INDELIVERS]);
00257
00258 nl_dump(p, " OutPkts OutOctets "
00259 " OutDiscards OutForwards\n");
00260
00261 nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]);
00262
00263 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTOCTETS],
00264 &octetsUnit);
00265 if (octets)
00266 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
00267 else
00268 nl_dump(p, "%16llu B ", 0);
00269
00270 nl_dump(p, "%18llu %18llu\n",
00271 link->l_stats[RTNL_LINK_IP6_OUTDISCARDS],
00272 link->l_stats[RTNL_LINK_IP6_OUTFORWDATAGRAMS]);
00273
00274 nl_dump(p, " InMcastPkts InMcastOctets "
00275 " InBcastPkts InBcastOctests\n");
00276
00277 nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]);
00278
00279 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INMCASTOCTETS],
00280 &octetsUnit);
00281 if (octets)
00282 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
00283 else
00284 nl_dump(p, "%16llu B ", 0);
00285
00286 nl_dump(p, "%18llu ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]);
00287 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS],
00288 &octetsUnit);
00289 if (octets)
00290 nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
00291 else
00292 nl_dump(p, "%16llu B\n", 0);
00293
00294 nl_dump(p, " OutMcastPkts OutMcastOctets "
00295 " OutBcastPkts OutBcastOctests\n");
00296
00297 nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]);
00298
00299 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTMCASTOCTETS],
00300 &octetsUnit);
00301 if (octets)
00302 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
00303 else
00304 nl_dump(p, "%16llu B ", 0);
00305
00306 nl_dump(p, "%18llu ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]);
00307 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS],
00308 &octetsUnit);
00309 if (octets)
00310 nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
00311 else
00312 nl_dump(p, "%16llu B\n", 0);
00313
00314 nl_dump(p, " ReasmOKs ReasmFails "
00315 " ReasmReqds ReasmTimeout\n");
00316 nl_dump(p, " %18llu %18llu %18llu %18llu\n",
00317 link->l_stats[RTNL_LINK_IP6_REASMOKS],
00318 link->l_stats[RTNL_LINK_IP6_REASMFAILS],
00319 link->l_stats[RTNL_LINK_IP6_REASMREQDS],
00320 link->l_stats[RTNL_LINK_IP6_REASMTIMEOUT]);
00321
00322 nl_dump(p, " FragOKs FragFails "
00323 " FragCreates\n");
00324 nl_dump(p, " %18llu %18llu %18llu\n",
00325 link->l_stats[RTNL_LINK_IP6_FRAGOKS],
00326 link->l_stats[RTNL_LINK_IP6_FRAGFAILS],
00327 link->l_stats[RTNL_LINK_IP6_FRAGCREATES]);
00328
00329 nl_dump(p, " InHdrErrors InTooBigErrors "
00330 " InNoRoutes InAddrErrors\n");
00331 nl_dump(p, " %18llu %18llu %18llu %18llu\n",
00332 link->l_stats[RTNL_LINK_IP6_INHDRERRORS],
00333 link->l_stats[RTNL_LINK_IP6_INTOOBIGERRORS],
00334 link->l_stats[RTNL_LINK_IP6_INNOROUTES],
00335 link->l_stats[RTNL_LINK_IP6_INADDRERRORS]);
00336
00337 nl_dump(p, " InUnknownProtos InTruncatedPkts "
00338 " OutNoRoutes\n");
00339 nl_dump(p, " %18llu %18llu %18llu\n",
00340 link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS],
00341 link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS],
00342 link->l_stats[RTNL_LINK_IP6_OUTNOROUTES]);
00343
00344 nl_dump(p, " ICMPv6: InMsgs InErrors "
00345 " OutMsgs OutErrors\n");
00346 nl_dump(p, " %18llu %18llu %18llu %18llu\n",
00347 link->l_stats[RTNL_LINK_ICMP6_INMSGS],
00348 link->l_stats[RTNL_LINK_ICMP6_INERRORS],
00349 link->l_stats[RTNL_LINK_ICMP6_OUTMSGS],
00350 link->l_stats[RTNL_LINK_ICMP6_OUTERRORS]);
00351 }
00352
00353 static const struct nla_policy protinfo_policy = {
00354 .type = NLA_NESTED,
00355 };
00356
00357 static struct rtnl_link_af_ops inet6_ops = {
00358 .ao_family = AF_INET6,
00359 .ao_alloc = &inet6_alloc,
00360 .ao_clone = &inet6_clone,
00361 .ao_free = &inet6_free,
00362 .ao_parse_protinfo = &inet6_parse_protinfo,
00363 .ao_parse_af = &inet6_parse_protinfo,
00364 .ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details,
00365 .ao_dump[NL_DUMP_STATS] = &inet6_dump_stats,
00366 .ao_protinfo_policy = &protinfo_policy,
00367 };
00368
00369 static void __init inet6_init(void)
00370 {
00371 rtnl_link_af_register(&inet6_ops);
00372 }
00373
00374 static void __exit inet6_exit(void)
00375 {
00376 rtnl_link_af_unregister(&inet6_ops);
00377 }