2
* lib/route/link/inet6.c AF_INET6 link operations
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
9
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
12
#include <netlink-local.h>
13
#include <netlink/netlink.h>
14
#include <netlink/attr.h>
15
#include <netlink/route/rtnl.h>
16
#include <netlink/route/link/api.h>
21
struct ifla_cacheinfo i6_cacheinfo;
22
uint32_t i6_conf[DEVCONF_MAX];
25
static void *inet6_alloc(struct rtnl_link *link)
27
return calloc(1, sizeof(struct inet6_data));
30
static void *inet6_clone(struct rtnl_link *link, void *data)
32
struct inet6_data *i6;
34
if ((i6 = inet6_alloc(link)))
35
memcpy(i6, data, sizeof(*i6));
40
static void inet6_free(struct rtnl_link *link, void *data)
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 = DEVCONF_MAX * 4 },
49
[IFLA_INET6_STATS] = { .minlen = __IPSTATS_MIB_MAX * 8 },
50
[IFLA_INET6_ICMP6STATS] = { .minlen = __ICMP6_MIB_MAX * 8 },
53
static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
56
struct inet6_data *i6 = data;
57
struct nlattr *tb[IFLA_INET6_MAX+1];
60
err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy);
64
if (tb[IFLA_INET6_FLAGS])
65
i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]);
67
if (tb[IFLA_INET6_CACHEINFO])
68
nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
69
sizeof(i6->i6_cacheinfo));
71
if (tb[IFLA_INET6_CONF])
72
nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
75
if (tb[IFLA_INET6_STATS]) {
76
uint64_t *cnt = nla_data(tb[IFLA_INET6_STATS]);
79
for (i = 1; i < __IPSTATS_MIB_MAX; i++)
80
rtnl_link_set_stat(link, RTNL_LINK_IP6_INPKTS + i - 1,
84
if (tb[IFLA_INET6_ICMP6STATS]) {
85
uint64_t *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
88
for (i = 1; i < __ICMP6_MIB_MAX; i++)
89
rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1,
96
/* These live in include/net/if_inet6.h and should be moved to include/linux */
97
#define IF_RA_OTHERCONF 0x80
98
#define IF_RA_MANAGED 0x40
99
#define IF_RA_RCVD 0x20
100
#define IF_RS_SENT 0x10
101
#define IF_READY 0x80000000
103
static const struct trans_tbl inet6_flags[] = {
104
__ADD(IF_RA_OTHERCONF, ra_otherconf)
105
__ADD(IF_RA_MANAGED, ra_managed)
106
__ADD(IF_RA_RCVD, ra_rcvd)
107
__ADD(IF_RS_SENT, rs_sent)
108
__ADD(IF_READY, ready)
111
static char *inet6_flags2str(int flags, char *buf, size_t len)
113
return __flags2str(flags, buf, len, inet6_flags,
114
ARRAY_SIZE(inet6_flags));
117
static const struct trans_tbl inet6_devconf[] = {
118
__ADD(DEVCONF_FORWARDING, forwarding)
119
__ADD(DEVCONF_HOPLIMIT, hoplimit)
120
__ADD(DEVCONF_MTU6, mtu6)
121
__ADD(DEVCONF_ACCEPT_RA, accept_ra)
122
__ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects)
123
__ADD(DEVCONF_AUTOCONF, autoconf)
124
__ADD(DEVCONF_DAD_TRANSMITS, dad_transmits)
125
__ADD(DEVCONF_RTR_SOLICITS, rtr_solicits)
126
__ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval)
127
__ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay)
128
__ADD(DEVCONF_USE_TEMPADDR, use_tempaddr)
129
__ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft)
130
__ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft)
131
__ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry)
132
__ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor)
133
__ADD(DEVCONF_MAX_ADDRESSES, max_addresses)
134
__ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version)
135
__ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr)
136
__ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo)
137
__ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref)
138
__ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval)
139
__ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info)
140
__ADD(DEVCONF_PROXY_NDP, proxy_ndp)
141
__ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad)
142
__ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route)
143
__ADD(DEVCONF_MC_FORWARDING, mc_forwarding)
144
__ADD(DEVCONF_DISABLE_IPV6, disable_ipv6)
145
__ADD(DEVCONF_ACCEPT_DAD, accept_dad)
146
__ADD(DEVCONF_FORCE_TLLAO, force_tllao)
149
static char *inet6_devconf2str(int type, char *buf, size_t len)
151
return __type2str(type, buf, len, inet6_devconf,
152
ARRAY_SIZE(inet6_devconf));
156
static void inet6_dump_details(struct rtnl_link *link,
157
struct nl_dump_params *p, void *data)
159
struct inet6_data *i6 = data;
160
char buf[64], buf2[64];
163
nl_dump_line(p, " ipv6 max-reasm-len %s",
164
nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf)));
166
nl_dump(p, " <%s>\n",
167
inet6_flags2str(i6->i6_flags, buf, sizeof(buf)));
170
nl_dump_line(p, " create-stamp %.2fs reachable-time %s",
171
(double) i6->i6_cacheinfo.tstamp / 100.,
172
nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf)));
174
nl_dump(p, " retrans-time %s\n",
175
nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf)));
177
nl_dump_line(p, " devconf:\n");
178
nl_dump_line(p, " ");
180
for (i = 0; i < DEVCONF_MAX; i++) {
181
uint32_t value = i6->i6_conf[i];
185
case DEVCONF_TEMP_VALID_LFT:
186
case DEVCONF_TEMP_PREFERED_LFT:
187
nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2));
190
case DEVCONF_RTR_PROBE_INTERVAL:
191
case DEVCONF_RTR_SOLICIT_INTERVAL:
192
case DEVCONF_RTR_SOLICIT_DELAY:
193
nl_msec2str(value, buf2, sizeof(buf2));
197
snprintf(buf2, sizeof(buf2), "%u", value);
202
inet6_devconf2str(i, buf, sizeof(buf));
204
offset = 23 - strlen(buf2);
208
for (x = strlen(buf); x < offset; x++)
211
strncpy(&buf[offset], buf2, strlen(buf2));
213
nl_dump_line(p, "%s", buf);
217
nl_dump_line(p, " ");
227
static void inet6_dump_stats(struct rtnl_link *link,
228
struct nl_dump_params *p, void *data)
233
nl_dump(p, " IPv6: InPkts InOctets "
234
" InDiscards InDelivers\n");
235
nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_INPKTS]);
237
octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INOCTETS],
240
nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
242
nl_dump(p, "%16llu B ", 0);
244
nl_dump(p, "%18llu %18llu\n",
245
link->l_stats[RTNL_LINK_IP6_INDISCARDS],
246
link->l_stats[RTNL_LINK_IP6_INDELIVERS]);
248
nl_dump(p, " OutPkts OutOctets "
249
" OutDiscards OutForwards\n");
251
nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]);
253
octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTOCTETS],
256
nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
258
nl_dump(p, "%16llu B ", 0);
260
nl_dump(p, "%18llu %18llu\n",
261
link->l_stats[RTNL_LINK_IP6_OUTDISCARDS],
262
link->l_stats[RTNL_LINK_IP6_OUTFORWDATAGRAMS]);
264
nl_dump(p, " InMcastPkts InMcastOctets "
265
" InBcastPkts InBcastOctests\n");
267
nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]);
269
octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INMCASTOCTETS],
272
nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
274
nl_dump(p, "%16llu B ", 0);
276
nl_dump(p, "%18llu ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]);
277
octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS],
280
nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
282
nl_dump(p, "%16llu B\n", 0);
284
nl_dump(p, " OutMcastPkts OutMcastOctets "
285
" OutBcastPkts OutBcastOctests\n");
287
nl_dump(p, " %18llu ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]);
289
octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTMCASTOCTETS],
292
nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
294
nl_dump(p, "%16llu B ", 0);
296
nl_dump(p, "%18llu ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]);
297
octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS],
300
nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
302
nl_dump(p, "%16llu B\n", 0);
304
nl_dump(p, " ReasmOKs ReasmFails "
305
" ReasmReqds ReasmTimeout\n");
306
nl_dump(p, " %18llu %18llu %18llu %18llu\n",
307
link->l_stats[RTNL_LINK_IP6_REASMOKS],
308
link->l_stats[RTNL_LINK_IP6_REASMFAILS],
309
link->l_stats[RTNL_LINK_IP6_REASMREQDS],
310
link->l_stats[RTNL_LINK_IP6_REASMTIMEOUT]);
312
nl_dump(p, " FragOKs FragFails "
314
nl_dump(p, " %18llu %18llu %18llu\n",
315
link->l_stats[RTNL_LINK_IP6_FRAGOKS],
316
link->l_stats[RTNL_LINK_IP6_FRAGFAILS],
317
link->l_stats[RTNL_LINK_IP6_FRAGCREATES]);
319
nl_dump(p, " InHdrErrors InTooBigErrors "
320
" InNoRoutes InAddrErrors\n");
321
nl_dump(p, " %18llu %18llu %18llu %18llu\n",
322
link->l_stats[RTNL_LINK_IP6_INHDRERRORS],
323
link->l_stats[RTNL_LINK_IP6_INTOOBIGERRORS],
324
link->l_stats[RTNL_LINK_IP6_INNOROUTES],
325
link->l_stats[RTNL_LINK_IP6_INADDRERRORS]);
327
nl_dump(p, " InUnknownProtos InTruncatedPkts "
329
nl_dump(p, " %18llu %18llu %18llu\n",
330
link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS],
331
link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS],
332
link->l_stats[RTNL_LINK_IP6_OUTNOROUTES]);
334
nl_dump(p, " ICMPv6: InMsgs InErrors "
335
" OutMsgs OutErrors\n");
336
nl_dump(p, " %18llu %18llu %18llu %18llu\n",
337
link->l_stats[RTNL_LINK_ICMP6_INMSGS],
338
link->l_stats[RTNL_LINK_ICMP6_INERRORS],
339
link->l_stats[RTNL_LINK_ICMP6_OUTMSGS],
340
link->l_stats[RTNL_LINK_ICMP6_OUTERRORS]);
343
static const struct nla_policy protinfo_policy = {
347
static struct rtnl_link_af_ops inet6_ops = {
348
.ao_family = AF_INET6,
349
.ao_alloc = &inet6_alloc,
350
.ao_clone = &inet6_clone,
351
.ao_free = &inet6_free,
352
.ao_parse_protinfo = &inet6_parse_protinfo,
353
.ao_parse_af = &inet6_parse_protinfo,
354
.ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details,
355
.ao_dump[NL_DUMP_STATS] = &inet6_dump_stats,
356
.ao_protinfo_policy = &protinfo_policy,
359
static void __init inet6_init(void)
361
rtnl_link_af_register(&inet6_ops);
364
static void __exit inet6_exit(void)
366
rtnl_link_af_unregister(&inet6_ops);