libnl: /data/src/libnl3/lib/route/link/inet6.c Source File

libnl 3.10.0

inet6.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
4 */
5
6#include "nl-default.h"
7
8#include <linux/ipv6.h>
9#include <linux/snmp.h>
10
11#include <netlink/netlink.h>
12#include <netlink/attr.h>
13#include <netlink/route/rtnl.h>
14#include <netlink/route/link/inet6.h>
15
16#include "nl-route.h"
17#include "link-api.h"
18#include "nl-priv-static-route/nl-priv-static-route.h"
19
20#define I6_ADDR_GEN_MODE_UNKNOWN UINT8_MAX
21
22 struct inet6_data
23{
24 uint32_t i6_flags;
25 struct ifla_cacheinfo i6_cacheinfo;
26 uint32_t i6_conf[DEVCONF_MAX];
27 struct in6_addr i6_token;
28 uint8_t i6_conf_len;
29 uint8_t i6_addr_gen_mode;
30};
31
32static void *inet6_alloc(struct rtnl_link *link)
33{
34 struct inet6_data *i6;
35
36 i6 = calloc(1, sizeof(struct inet6_data));
37 if (i6)
38 i6->i6_addr_gen_mode = I6_ADDR_GEN_MODE_UNKNOWN;
39
40 return i6;
41}
42
43static void *inet6_clone(struct rtnl_link *link, void *data)
44{
45 struct inet6_data *i6;
46
47 if ((i6 = inet6_alloc(link)))
48 memcpy(i6, data, sizeof(*i6));
49
50 return i6;
51}
52
53static void inet6_free(struct rtnl_link *link, void *data)
54{
55 free(data);
56}
57
58static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
59 [IFLA_INET6_FLAGS] = { .type = NLA_U32 },
60 [IFLA_INET6_CACHEINFO] = { .minlen = sizeof(struct ifla_cacheinfo) },
61 [IFLA_INET6_CONF] = { .minlen = 4 },
62 [IFLA_INET6_STATS] = { .minlen = 8 },
63 [IFLA_INET6_ICMP6STATS] = { .minlen = 8 },
64 [IFLA_INET6_TOKEN] = { .minlen = sizeof(struct in6_addr) },
65 [IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 },
66};
67
68static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = {
69 /* 14a196807482e6fc74f15fc03176d5c08880588f^:include/linux/snmp.h
70 * version before the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f.
71 * This version was valid since commit edf391ff17232f097d72441c9ad467bcb3b5db18, which
72 * predates support for parsing IFLA_PROTINFO in libnl3. Such an even older meaning of
73 * the flags is not supported in libnl3. */
74 [ 1] = RTNL_LINK_IP6_INPKTS, /* IPSTATS_MIB_INPKTS */
75 [ 2] = RTNL_LINK_IP6_INHDRERRORS, /* IPSTATS_MIB_INHDRERRORS */
76 [ 3] = RTNL_LINK_IP6_INTOOBIGERRORS, /* IPSTATS_MIB_INTOOBIGERRORS */
77 [ 4] = RTNL_LINK_IP6_INNOROUTES, /* IPSTATS_MIB_INNOROUTES */
78 [ 5] = RTNL_LINK_IP6_INADDRERRORS, /* IPSTATS_MIB_INADDRERRORS */
79 [ 6] = RTNL_LINK_IP6_INUNKNOWNPROTOS, /* IPSTATS_MIB_INUNKNOWNPROTOS */
80 [ 7] = RTNL_LINK_IP6_INTRUNCATEDPKTS, /* IPSTATS_MIB_INTRUNCATEDPKTS */
81 [ 8] = RTNL_LINK_IP6_INDISCARDS, /* IPSTATS_MIB_INDISCARDS */
82 [ 9] = RTNL_LINK_IP6_INDELIVERS, /* IPSTATS_MIB_INDELIVERS */
83 [10] = RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* IPSTATS_MIB_OUTFORWDATAGRAMS */
84 [11] = RTNL_LINK_IP6_OUTPKTS, /* IPSTATS_MIB_OUTPKTS */
85 [12] = RTNL_LINK_IP6_OUTDISCARDS, /* IPSTATS_MIB_OUTDISCARDS */
86 [13] = RTNL_LINK_IP6_OUTNOROUTES, /* IPSTATS_MIB_OUTNOROUTES */
87 [14] = RTNL_LINK_IP6_REASMTIMEOUT, /* IPSTATS_MIB_REASMTIMEOUT */
88 [15] = RTNL_LINK_IP6_REASMREQDS, /* IPSTATS_MIB_REASMREQDS */
89 [16] = RTNL_LINK_IP6_REASMOKS, /* IPSTATS_MIB_REASMOKS */
90 [17] = RTNL_LINK_IP6_REASMFAILS, /* IPSTATS_MIB_REASMFAILS */
91 [18] = RTNL_LINK_IP6_FRAGOKS, /* IPSTATS_MIB_FRAGOKS */
92 [19] = RTNL_LINK_IP6_FRAGFAILS, /* IPSTATS_MIB_FRAGFAILS */
93 [20] = RTNL_LINK_IP6_FRAGCREATES, /* IPSTATS_MIB_FRAGCREATES */
94 [21] = RTNL_LINK_IP6_INMCASTPKTS, /* IPSTATS_MIB_INMCASTPKTS */
95 [22] = RTNL_LINK_IP6_OUTMCASTPKTS, /* IPSTATS_MIB_OUTMCASTPKTS */
96 [23] = RTNL_LINK_IP6_INBCASTPKTS, /* IPSTATS_MIB_INBCASTPKTS */
97 [24] = RTNL_LINK_IP6_OUTBCASTPKTS, /* IPSTATS_MIB_OUTBCASTPKTS */
98 [25] = RTNL_LINK_IP6_INOCTETS, /* IPSTATS_MIB_INOCTETS */
99 [26] = RTNL_LINK_IP6_OUTOCTETS, /* IPSTATS_MIB_OUTOCTETS */
100 [27] = RTNL_LINK_IP6_INMCASTOCTETS, /* IPSTATS_MIB_INMCASTOCTETS */
101 [28] = RTNL_LINK_IP6_OUTMCASTOCTETS, /* IPSTATS_MIB_OUTMCASTOCTETS */
102 [29] = RTNL_LINK_IP6_INBCASTOCTETS, /* IPSTATS_MIB_INBCASTOCTETS */
103 [30] = RTNL_LINK_IP6_OUTBCASTOCTETS, /* IPSTATS_MIB_OUTBCASTOCTETS */
104};
105
106static const uint8_t map_stat_id_from_IPSTATS_MIB_v2[__IPSTATS_MIB_MAX] = {
107 /* d8ec26d7f8287f5788a494f56e8814210f0e64be:include/uapi/linux/snmp.h
108 * version since the API change in commit 14a196807482e6fc74f15fc03176d5c08880588f */
109 [ 1] = RTNL_LINK_IP6_INPKTS, /* IPSTATS_MIB_INPKTS */
110 [ 2] = RTNL_LINK_IP6_INOCTETS, /* IPSTATS_MIB_INOCTETS */
111 [ 3] = RTNL_LINK_IP6_INDELIVERS, /* IPSTATS_MIB_INDELIVERS */
112 [ 4] = RTNL_LINK_IP6_OUTFORWDATAGRAMS, /* IPSTATS_MIB_OUTFORWDATAGRAMS */
113 [ 5] = RTNL_LINK_IP6_OUTPKTS, /* IPSTATS_MIB_OUTPKTS */
114 [ 6] = RTNL_LINK_IP6_OUTOCTETS, /* IPSTATS_MIB_OUTOCTETS */
115 [ 7] = RTNL_LINK_IP6_INHDRERRORS, /* IPSTATS_MIB_INHDRERRORS */
116 [ 8] = RTNL_LINK_IP6_INTOOBIGERRORS, /* IPSTATS_MIB_INTOOBIGERRORS */
117 [ 9] = RTNL_LINK_IP6_INNOROUTES, /* IPSTATS_MIB_INNOROUTES */
118 [10] = RTNL_LINK_IP6_INADDRERRORS, /* IPSTATS_MIB_INADDRERRORS */
119 [11] = RTNL_LINK_IP6_INUNKNOWNPROTOS, /* IPSTATS_MIB_INUNKNOWNPROTOS */
120 [12] = RTNL_LINK_IP6_INTRUNCATEDPKTS, /* IPSTATS_MIB_INTRUNCATEDPKTS */
121 [13] = RTNL_LINK_IP6_INDISCARDS, /* IPSTATS_MIB_INDISCARDS */
122 [14] = RTNL_LINK_IP6_OUTDISCARDS, /* IPSTATS_MIB_OUTDISCARDS */
123 [15] = RTNL_LINK_IP6_OUTNOROUTES, /* IPSTATS_MIB_OUTNOROUTES */
124 [16] = RTNL_LINK_IP6_REASMTIMEOUT, /* IPSTATS_MIB_REASMTIMEOUT */
125 [17] = RTNL_LINK_IP6_REASMREQDS, /* IPSTATS_MIB_REASMREQDS */
126 [18] = RTNL_LINK_IP6_REASMOKS, /* IPSTATS_MIB_REASMOKS */
127 [19] = RTNL_LINK_IP6_REASMFAILS, /* IPSTATS_MIB_REASMFAILS */
128 [20] = RTNL_LINK_IP6_FRAGOKS, /* IPSTATS_MIB_FRAGOKS */
129 [21] = RTNL_LINK_IP6_FRAGFAILS, /* IPSTATS_MIB_FRAGFAILS */
130 [22] = RTNL_LINK_IP6_FRAGCREATES, /* IPSTATS_MIB_FRAGCREATES */
131 [23] = RTNL_LINK_IP6_INMCASTPKTS, /* IPSTATS_MIB_INMCASTPKTS */
132 [24] = RTNL_LINK_IP6_OUTMCASTPKTS, /* IPSTATS_MIB_OUTMCASTPKTS */
133 [25] = RTNL_LINK_IP6_INBCASTPKTS, /* IPSTATS_MIB_INBCASTPKTS */
134 [26] = RTNL_LINK_IP6_OUTBCASTPKTS, /* IPSTATS_MIB_OUTBCASTPKTS */
135 [27] = RTNL_LINK_IP6_INMCASTOCTETS, /* IPSTATS_MIB_INMCASTOCTETS */
136 [28] = RTNL_LINK_IP6_OUTMCASTOCTETS, /* IPSTATS_MIB_OUTMCASTOCTETS */
137 [29] = RTNL_LINK_IP6_INBCASTOCTETS, /* IPSTATS_MIB_INBCASTOCTETS */
138 [30] = RTNL_LINK_IP6_OUTBCASTOCTETS, /* IPSTATS_MIB_OUTBCASTOCTETS */
139 [31] = RTNL_LINK_IP6_CSUMERRORS, /* IPSTATS_MIB_CSUMERRORS */
140 [32] = RTNL_LINK_IP6_NOECTPKTS, /* IPSTATS_MIB_NOECTPKTS */
141 [33] = RTNL_LINK_IP6_ECT1PKTS, /* IPSTATS_MIB_ECT1PKTS */
142 [34] = RTNL_LINK_IP6_ECT0PKTS, /* IPSTATS_MIB_ECT0PKTS */
143 [35] = RTNL_LINK_IP6_CEPKTS, /* IPSTATS_MIB_CEPKTS */
144 [36] = RTNL_LINK_REASM_OVERLAPS, /* IPSTATS_MIB_REASM_OVERLAPS */
145};
146
147const uint8_t *const _nltst_map_stat_id_from_IPSTATS_MIB_v2 = map_stat_id_from_IPSTATS_MIB_v2;
148
149static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
150 void *data)
151{
152 struct inet6_data *i6 = data;
153 struct nlattr *tb[IFLA_INET6_MAX+1];
154 int err;
155
156 err = nla_parse_nested(tb, IFLA_INET6_MAX, attr, inet6_policy);
157 if (err < 0)
158 return err;
159 if (tb[IFLA_INET6_CONF] && nla_len(tb[IFLA_INET6_CONF]) % 4)
160 return -EINVAL;
161 if (tb[IFLA_INET6_STATS] && nla_len(tb[IFLA_INET6_STATS]) % 8)
162 return -EINVAL;
163 if (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8)
164 return -EINVAL;
165
166 if (tb[IFLA_INET6_FLAGS])
167 i6->i6_flags = nla_get_u32(tb[IFLA_INET6_FLAGS]);
168
169 if (tb[IFLA_INET6_CACHEINFO])
170 nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
171 sizeof(i6->i6_cacheinfo));
172
173 if (tb[IFLA_INET6_CONF]) {
174 i6->i6_conf_len = _NL_MIN(ARRAY_SIZE(i6->i6_conf),
175 nla_len(tb[IFLA_INET6_CONF]) /
176 sizeof(i6->i6_conf[0]));
177 nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
178 sizeof(i6->i6_conf[0]) * i6->i6_conf_len);
179 }
180
181 if (tb[IFLA_INET6_TOKEN])
182 nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN],
183 sizeof(struct in6_addr));
184
185 if (tb[IFLA_INET6_ADDR_GEN_MODE])
186 i6->i6_addr_gen_mode = nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]);
187
188 /*
189 * Due to 32bit data alignment, these addresses must be copied to an
190 * aligned location prior to access.
191 */
192 if (tb[IFLA_INET6_STATS]) {
193 unsigned char *cnt = nla_data(tb[IFLA_INET6_STATS]);
194 uint64_t stat;
195 int i;
196 int len = nla_len(tb[IFLA_INET6_STATS]) / 8;
197 const uint8_t *map_stat_id = map_stat_id_from_IPSTATS_MIB_v2;
198
199 if (len < 32 ||
200 (tb[IFLA_INET6_ICMP6STATS] && nla_len(tb[IFLA_INET6_ICMP6STATS]) < 6)) {
201 /* kernel commit 14a196807482e6fc74f15fc03176d5c08880588f reordered the values.
202 * The later commit 6a5dc9e598fe90160fee7de098fa319665f5253e added values
203 * IPSTATS_MIB_CSUMERRORS/ICMP6_MIB_CSUMERRORS. If the netlink is shorter
204 * then this, assume that the kernel uses the previous meaning of the
205 * enumeration. */
206 map_stat_id = map_stat_id_from_IPSTATS_MIB_v1;
207 }
208
209 len = _NL_MIN(__IPSTATS_MIB_MAX, len);
210 for (i = 1; i < len; i++) {
211 memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
212 rtnl_link_set_stat(link, map_stat_id[i], stat);
213 }
214 }
215
216 if (tb[IFLA_INET6_ICMP6STATS]) {
217#define _NL_ICMP6_MIB_MAX 6
218 unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
219 uint64_t stat;
220 int i;
221 int len = _NL_MIN(_NL_ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
222
223 _NL_STATIC_ASSERT (__ICMP6_MIB_MAX >= _NL_ICMP6_MIB_MAX);
224 _NL_STATIC_ASSERT (RTNL_LINK_ICMP6_CSUMERRORS - RTNL_LINK_ICMP6_INMSGS + 1 == 5);
225
226 for (i = 1; i < len; i++) {
227 memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
228 rtnl_link_set_stat(link, RTNL_LINK_ICMP6_INMSGS + i - 1,
229 stat);
230 }
231 }
232
233 return 0;
234}
235
236static int inet6_fill_af(struct rtnl_link *link, struct nl_msg *msg, void *data)
237{
238 struct inet6_data *id = data;
239
240 if (id->i6_addr_gen_mode != I6_ADDR_GEN_MODE_UNKNOWN)
241 NLA_PUT_U8(msg, IFLA_INET6_ADDR_GEN_MODE, id->i6_addr_gen_mode);
242
243 return 0;
244
245nla_put_failure:
246 return -NLE_MSGSIZE;
247}
248
249/* These live in include/net/if_inet6.h and should be moved to include/linux */
250#define IF_RA_OTHERCONF 0x80
251#define IF_RA_MANAGED 0x40
252#define IF_RA_RCVD 0x20
253#define IF_RS_SENT 0x10
254#define IF_READY 0x80000000
255
256static const struct trans_tbl inet6_flags[] = {
257 __ADD(IF_RA_OTHERCONF, ra_otherconf),
258 __ADD(IF_RA_MANAGED, ra_managed),
259 __ADD(IF_RA_RCVD, ra_rcvd),
260 __ADD(IF_RS_SENT, rs_sent),
261 __ADD(IF_READY, ready),
262};
263
264char *rtnl_link_inet6_flags2str(int flags, char *buf, size_t len)
265{
266 return __flags2str(flags, buf, len, inet6_flags,
267 ARRAY_SIZE(inet6_flags));
268}
269
270int rtnl_link_inet6_str2flags(const char *name)
271{
272 return __str2flags(name, inet6_flags, ARRAY_SIZE(inet6_flags));
273}
274
275static const struct trans_tbl inet6_devconf[] = {
276 __ADD(DEVCONF_FORWARDING, forwarding),
277 __ADD(DEVCONF_HOPLIMIT, hoplimit),
278 __ADD(DEVCONF_MTU6, mtu6),
279 __ADD(DEVCONF_ACCEPT_RA, accept_ra),
280 __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects),
281 __ADD(DEVCONF_AUTOCONF, autoconf),
282 __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits),
283 __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits),
284 __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval),
285 __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay),
286 __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr),
287 __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft),
288 __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft),
289 __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry),
290 __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor),
291 __ADD(DEVCONF_MAX_ADDRESSES, max_addresses),
292 __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version),
293 __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr),
294 __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo),
295 __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref),
296 __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval),
297 __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info),
298 __ADD(DEVCONF_PROXY_NDP, proxy_ndp),
299 __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad),
300 __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route),
301 __ADD(DEVCONF_MC_FORWARDING, mc_forwarding),
302 __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6),
303 __ADD(DEVCONF_ACCEPT_DAD, accept_dad),
304 __ADD(DEVCONF_FORCE_TLLAO, force_tllao),
305};
306
307static char *inet6_devconf2str(int type, char *buf, size_t len)
308{
309 return __type2str(type, buf, len, inet6_devconf,
310 ARRAY_SIZE(inet6_devconf));
311}
312
313static const struct trans_tbl inet6_addr_gen_mode[] = {
314 __ADD(IN6_ADDR_GEN_MODE_EUI64, eui64),
315 __ADD(IN6_ADDR_GEN_MODE_NONE, none),
316 __ADD(IN6_ADDR_GEN_MODE_STABLE_PRIVACY, stable_privacy),
317};
318
319const char *rtnl_link_inet6_addrgenmode2str(uint8_t mode, char *buf, size_t len)
320{
321 return __type2str(mode, buf, len, inet6_addr_gen_mode,
322 ARRAY_SIZE(inet6_addr_gen_mode));
323}
324
325uint8_t rtnl_link_inet6_str2addrgenmode(const char *mode)
326{
327 return (uint8_t) __str2type(mode, inet6_addr_gen_mode,
328 ARRAY_SIZE(inet6_addr_gen_mode));
329}
330
331static void inet6_dump_details(struct rtnl_link *link,
332 struct nl_dump_params *p, void *data)
333{
334 struct inet6_data *i6 = data;
335 struct nl_addr *addr;
336 int i, n = 0;
337 char buf[64];
338
339 nl_dump_line(p, " ipv6 max-reasm-len %s",
340 nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, sizeof(buf)));
341
342 nl_dump(p, " <%s>\n",
343 rtnl_link_inet6_flags2str(i6->i6_flags, buf, sizeof(buf)));
344
345 nl_dump_line(p, " create-stamp %.2fs reachable-time %s",
346 (double) i6->i6_cacheinfo.tstamp / 100.,
347 nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, sizeof(buf)));
348
349 nl_dump(p, " retrans-time %s\n",
350 nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf)));
351
352 addr = nl_addr_build(AF_INET6, &i6->i6_token, sizeof(i6->i6_token));
353 nl_dump(p, " token %s\n",
354 nl_addr2str(addr, buf, sizeof(buf)));
355 nl_addr_put(addr);
356
357 nl_dump(p, " link-local address mode %s\n",
358 rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode,
359 buf, sizeof(buf)));
360
361 nl_dump_line(p, " devconf:\n");
362 nl_dump_line(p, " ");
363
364 for (i = 0; i < (int) i6->i6_conf_len; i++) {
365 char buf2[64];
366 uint32_t value = i6->i6_conf[i];
367 int x, offset;
368
369 switch (i) {
370 case DEVCONF_TEMP_VALID_LFT:
371 case DEVCONF_TEMP_PREFERED_LFT:
372 nl_msec2str((uint64_t) value * 1000., buf2, sizeof(buf2));
373 break;
374
375 case DEVCONF_RTR_PROBE_INTERVAL:
376 case DEVCONF_RTR_SOLICIT_INTERVAL:
377 case DEVCONF_RTR_SOLICIT_DELAY:
378 nl_msec2str(value, buf2, sizeof(buf2));
379 break;
380
381 default:
382 snprintf(buf2, sizeof(buf2), "%u", value);
383 break;
384 }
385
386 inet6_devconf2str(i, buf, sizeof(buf));
387
388 offset = 23 - strlen(buf2);
389 if (offset < 0)
390 offset = 0;
391
392 for (x = strlen(buf); x < offset; x++)
393 buf[x] = ' ';
394
395 _nl_strncpy_trunc(&buf[offset], buf2, sizeof(buf) - offset);
396
397 nl_dump_line(p, "%s", buf);
398
399 if (++n == 3) {
400 nl_dump(p, "\n");
401 nl_dump_line(p, " ");
402 n = 0;
403 } else
404 nl_dump(p, " ");
405 }
406
407 if (n != 0)
408 nl_dump(p, "\n");
409}
410
411static void inet6_dump_stats(struct rtnl_link *link,
412 struct nl_dump_params *p, void *data)
413{
414 double octets;
415 char *octetsUnit;
416
417 nl_dump(p, " IPv6: InPkts InOctets "
418 " InDiscards InDelivers\n");
419 nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INPKTS]);
420
421 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INOCTETS],
422 &octetsUnit);
423 if (octets)
424 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
425 else
426 nl_dump(p, "%16u B ", 0);
427
428 nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n",
429 link->l_stats[RTNL_LINK_IP6_INDISCARDS],
430 link->l_stats[RTNL_LINK_IP6_INDELIVERS]);
431
432 nl_dump(p, " OutPkts OutOctets "
433 " OutDiscards OutForwards\n");
434
435 nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTPKTS]);
436
437 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTOCTETS],
438 &octetsUnit);
439 if (octets)
440 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
441 else
442 nl_dump(p, "%16u B ", 0);
443
444 nl_dump(p, "%18" PRIu64 " %18" PRIu64 "\n",
445 link->l_stats[RTNL_LINK_IP6_OUTDISCARDS],
446 link->l_stats[RTNL_LINK_IP6_OUTFORWDATAGRAMS]);
447
448 nl_dump(p, " InMcastPkts InMcastOctets "
449 " InBcastPkts InBcastOctests\n");
450
451 nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INMCASTPKTS]);
452
453 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INMCASTOCTETS],
454 &octetsUnit);
455 if (octets)
456 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
457 else
458 nl_dump(p, "%16u B ", 0);
459
460 nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_INBCASTPKTS]);
461 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_INBCASTOCTETS],
462 &octetsUnit);
463 if (octets)
464 nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
465 else
466 nl_dump(p, "%16u B\n", 0);
467
468 nl_dump(p, " OutMcastPkts OutMcastOctets "
469 " OutBcastPkts OutBcastOctests\n");
470
471 nl_dump(p, " %18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTMCASTPKTS]);
472
473 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTMCASTOCTETS],
474 &octetsUnit);
475 if (octets)
476 nl_dump(p, "%14.2f %3s ", octets, octetsUnit);
477 else
478 nl_dump(p, "%16u B ", 0);
479
480 nl_dump(p, "%18" PRIu64 " ", link->l_stats[RTNL_LINK_IP6_OUTBCASTPKTS]);
481 octets = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_IP6_OUTBCASTOCTETS],
482 &octetsUnit);
483 if (octets)
484 nl_dump(p, "%14.2f %3s\n", octets, octetsUnit);
485 else
486 nl_dump(p, "%16u B\n", 0);
487
488 nl_dump(p, " ReasmOKs ReasmFails "
489 " ReasmReqds ReasmTimeout\n");
490 nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
491 link->l_stats[RTNL_LINK_IP6_REASMOKS],
492 link->l_stats[RTNL_LINK_IP6_REASMFAILS],
493 link->l_stats[RTNL_LINK_IP6_REASMREQDS],
494 link->l_stats[RTNL_LINK_IP6_REASMTIMEOUT]);
495
496 nl_dump(p, " FragOKs FragFails "
497 " FragCreates\n");
498 nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
499 link->l_stats[RTNL_LINK_IP6_FRAGOKS],
500 link->l_stats[RTNL_LINK_IP6_FRAGFAILS],
501 link->l_stats[RTNL_LINK_IP6_FRAGCREATES]);
502
503 nl_dump(p, " InHdrErrors InTooBigErrors "
504 " InNoRoutes InAddrErrors\n");
505 nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
506 link->l_stats[RTNL_LINK_IP6_INHDRERRORS],
507 link->l_stats[RTNL_LINK_IP6_INTOOBIGERRORS],
508 link->l_stats[RTNL_LINK_IP6_INNOROUTES],
509 link->l_stats[RTNL_LINK_IP6_INADDRERRORS]);
510
511 nl_dump(p, " InUnknownProtos InTruncatedPkts "
512 " OutNoRoutes InCsumErrors\n");
513 nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
514 link->l_stats[RTNL_LINK_IP6_INUNKNOWNPROTOS],
515 link->l_stats[RTNL_LINK_IP6_INTRUNCATEDPKTS],
516 link->l_stats[RTNL_LINK_IP6_OUTNOROUTES],
517 link->l_stats[RTNL_LINK_IP6_CSUMERRORS]);
518
519 nl_dump(p, " InNoECTPkts InECT1Pkts "
520 " InECT0Pkts InCEPkts\n");
521 nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
522 link->l_stats[RTNL_LINK_IP6_NOECTPKTS],
523 link->l_stats[RTNL_LINK_IP6_ECT1PKTS],
524 link->l_stats[RTNL_LINK_IP6_ECT0PKTS],
525 link->l_stats[RTNL_LINK_IP6_CEPKTS]);
526
527 nl_dump(p, " ICMPv6: InMsgs InErrors "
528 " OutMsgs OutErrors InCsumErrors\n");
529 nl_dump(p, " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 " %18" PRIu64 "\n",
530 link->l_stats[RTNL_LINK_ICMP6_INMSGS],
531 link->l_stats[RTNL_LINK_ICMP6_INERRORS],
532 link->l_stats[RTNL_LINK_ICMP6_OUTMSGS],
533 link->l_stats[RTNL_LINK_ICMP6_OUTERRORS],
534 link->l_stats[RTNL_LINK_ICMP6_CSUMERRORS]);
535}
536
537static const struct nla_policy protinfo_policy = {
538 .type = NLA_NESTED,
539};
540
541static struct rtnl_link_af_ops inet6_ops = {
542 .ao_family = AF_INET6,
543 .ao_alloc = &inet6_alloc,
544 .ao_clone = &inet6_clone,
545 .ao_free = &inet6_free,
546 .ao_parse_protinfo = &inet6_parse_protinfo,
547 .ao_parse_af = &inet6_parse_protinfo,
548 .ao_fill_af = &inet6_fill_af,
549 .ao_dump[NL_DUMP_DETAILS] = &inet6_dump_details,
550 .ao_dump[NL_DUMP_STATS] = &inet6_dump_stats,
551 .ao_protinfo_policy = &protinfo_policy,
552};
553
554/**
555 * Return IPv6 specific flags
556 * @arg link Link object
557 * @arg out_flags Flags on success
558 *
559 * Returns the link's IPv6 flags.
560 *
561 * @return 0 on success
562 * @return -NLE_NOATTR configuration setting not available
563 */
564int rtnl_link_inet6_get_flags(struct rtnl_link *link, uint32_t* out_flags)
565{
566 struct inet6_data *id = NULL;
567
568 if (!(id = rtnl_link_af_data(link, &inet6_ops)))
569 return -NLE_NOATTR;
570
571 *out_flags = id->i6_flags;
572 return 0;
573}
574
575/**
576 * Set IPv6 specific flags
577 * @arg link Link object
578 * @arg flags Flags to set
579 *
580 * Sets the link's IPv6 specific flags. Overwrites currently set flags.
581 *
582 * @return 0 on success
583 * @return -NLE_NOMEM could not allocate inet6 data
584 */
585int rtnl_link_inet6_set_flags(struct rtnl_link *link, uint32_t flags)
586{
587 struct inet6_data *id;
588
589 if (!(id = rtnl_link_af_alloc(link, &inet6_ops)))
590 return -NLE_NOMEM;
591
592 id->i6_flags = flags;
593 return 0;
594}
595
596/**
597 * Get IPv6 tokenized interface identifier
598 * @arg link Link object
599 * @arg token Tokenized interface identifier on success
600 *
601 * Returns the link's IPv6 tokenized interface identifier.
602 *
603 * @return 0 on success
604 * @return -NLE_NOMEM failure to allocate struct nl_addr result
605 * @return -NLE_NOATTR configuration setting not available
606 * @return -NLE_NOADDR tokenized interface identifier is not set
607 */
608int rtnl_link_inet6_get_token(struct rtnl_link *link, struct nl_addr **addr)
609{
610 struct inet6_data *id;
611
612 if (!(id = rtnl_link_af_data(link, &inet6_ops)))
613 return -NLE_NOATTR;
614
615 *addr = nl_addr_build(AF_INET6, &id->i6_token, sizeof(id->i6_token));
616 if (!*addr)
617 return -NLE_NOMEM;
618 if (nl_addr_iszero(*addr)) {
619 nl_addr_put(*addr);
620 *addr = NULL;
621 return -NLE_NOADDR;
622 }
623
624 return 0;
625}
626
627/**
628 * Set IPv6 tokenized interface identifier
629 * @arg link Link object
630 * @arg token Tokenized interface identifier
631 *
632 * Sets the link's IPv6 tokenized interface identifier.
633 *
634 * @return 0 on success
635 * @return -NLE_NOMEM could not allocate inet6 data
636 * @return -NLE_INVAL addr is not a valid inet6 address
637 */
638int rtnl_link_inet6_set_token(struct rtnl_link *link, struct nl_addr *addr)
639{
640 struct inet6_data *id;
641
642 if ((nl_addr_get_family(addr) != AF_INET6) ||
643 (nl_addr_get_len(addr) != sizeof(id->i6_token)))
644 return -NLE_INVAL;
645
646 if (!(id = rtnl_link_af_alloc(link, &inet6_ops)))
647 return -NLE_NOMEM;
648
649 memcpy(&id->i6_token, nl_addr_get_binary_addr(addr),
650 sizeof(id->i6_token));
651 return 0;
652}
653
654/**
655 * Get IPv6 link-local address generation mode
656 * @arg link Link object
657 * @arg mode Generation mode on success
658 *
659 * Returns the link's IPv6 link-local address generation mode.
660 *
661 * @return 0 on success
662 * @return -NLE_NOATTR configuration setting not available
663 * @return -NLE_INVAL generation mode unknown. If the link was received via
664 * netlink, it means that address generation mode is not
665 * supported by the kernel.
666 */
667int rtnl_link_inet6_get_addr_gen_mode(struct rtnl_link *link, uint8_t *mode)
668{
669 struct inet6_data *id;
670
671 if (!(id = rtnl_link_af_data(link, &inet6_ops)))
672 return -NLE_NOATTR;
673
674 if (id->i6_addr_gen_mode == I6_ADDR_GEN_MODE_UNKNOWN)
675 return -NLE_INVAL;
676
677 *mode = id->i6_addr_gen_mode;
678 return 0;
679}
680
681/**
682 * Set IPv6 link-local address generation mode
683 * @arg link Link object
684 * @arg mode Generation mode
685 *
686 * Sets the link's IPv6 link-local address generation mode.
687 *
688 * @return 0 on success
689 * @return -NLE_NOMEM could not allocate inet6 data
690 */
691int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *link, uint8_t mode)
692{
693 struct inet6_data *id;
694
695 if (!(id = rtnl_link_af_alloc(link, &inet6_ops)))
696 return -NLE_NOMEM;
697
698 id->i6_addr_gen_mode = mode;
699 return 0;
700}
701
702/**
703 * Get value of a ipv6 link configuration setting
704 * @arg link Link object
705 * @arg cfgid Configuration identifier
706 * @arg res Result pointer
707 *
708 * Stores the value of the specified configuration setting in the provided
709 * result pointer.
710 *
711 * @return 0 on success or a negative error code.
712 * @return -NLE_RANGE cfgid is out of range or not provided by kernel.
713 * @return -NLE_NOATTR configuration setting not available
714 */
715int rtnl_link_inet6_get_conf(struct rtnl_link *link, unsigned int cfgid,
716 uint32_t *res)
717{
718 struct inet6_data *id;
719
720 if (!(id = rtnl_link_af_data(link, &inet6_ops)))
721 return -NLE_NOATTR;
722
723 if (cfgid >= id->i6_conf_len)
724 return -NLE_RANGE;
725
726 *res = id->i6_conf[cfgid];
727
728 return 0;
729}
730
731
732static void _nl_init inet6_init(void)
733{
734 rtnl_link_af_register(&inet6_ops);
735}
736
737static void _nl_exit inet6_exit(void)
738{
739 rtnl_link_af_unregister(&inet6_ops);
740}
nl_addr_iszero
int nl_addr_iszero(const struct nl_addr *addr)
Returns true if the address consists of all zeros.
Definition addr.c:652
nl_addr_build
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
Definition addr.c:216
nl_addr_get_binary_addr
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition addr.c:943
nl_addr_get_family
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
Definition addr.c:895
nl_addr2str
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition addr.c:1001
nl_addr_get_len
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition addr.c:955
nl_addr_put
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition addr.c:541
nla_get_u32
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:712
NLA_PUT_U8
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:194
nla_data
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
nla_get_u8
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:612
nla_memcpy
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:353
nla_parse_nested
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1035
nla_len
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
NLA_U8
@ NLA_U8
8 bit integer
Definition attr.h:35
NLA_NESTED
@ NLA_NESTED
Nested attributes.
Definition attr.h:42
NLA_U32
@ NLA_U32
32 bit integer
Definition attr.h:37
rtnl_link_af_alloc
void * rtnl_link_af_alloc(struct rtnl_link *link, const struct rtnl_link_af_ops *ops)
Allocate and return data buffer for link address family modules.
Definition api.c:249
rtnl_link_af_unregister
int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
Unregister operations for a link address family.
Definition api.c:344
rtnl_link_af_register
int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
Register operations for a link address family.
Definition api.c:305
rtnl_link_af_data
void * rtnl_link_af_data(const struct rtnl_link *link, const struct rtnl_link_af_ops *ops)
Return data buffer for link address family modules.
Definition api.c:284
rtnl_link_set_stat
int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id, const uint64_t value)
Set value of link statistics counter.
Definition link.c:2535
RTNL_LINK_IP6_INBCASTOCTETS
@ RTNL_LINK_IP6_INBCASTOCTETS
Definition link.h:83
RTNL_LINK_IP6_ECT0PKTS
@ RTNL_LINK_IP6_ECT0PKTS
Definition link.h:93
RTNL_LINK_REASM_OVERLAPS
@ RTNL_LINK_REASM_OVERLAPS
Definition link.h:96
RTNL_LINK_IP6_INTRUNCATEDPKTS
@ RTNL_LINK_IP6_INTRUNCATEDPKTS
Definition link.h:61
RTNL_LINK_ICMP6_INMSGS
@ RTNL_LINK_ICMP6_INMSGS
Definition link.h:85
RTNL_LINK_IP6_INNOROUTES
@ RTNL_LINK_IP6_INNOROUTES
Definition link.h:58
RTNL_LINK_IP6_OUTMCASTOCTETS
@ RTNL_LINK_IP6_OUTMCASTOCTETS
Definition link.h:82
RTNL_LINK_IP6_INMCASTPKTS
@ RTNL_LINK_IP6_INMCASTPKTS
Definition link.h:75
RTNL_LINK_IP6_REASMOKS
@ RTNL_LINK_IP6_REASMOKS
Definition link.h:70
RTNL_LINK_IP6_OUTBCASTOCTETS
@ RTNL_LINK_IP6_OUTBCASTOCTETS
Definition link.h:84
RTNL_LINK_IP6_INDELIVERS
@ RTNL_LINK_IP6_INDELIVERS
Definition link.h:63
RTNL_LINK_IP6_REASMTIMEOUT
@ RTNL_LINK_IP6_REASMTIMEOUT
Definition link.h:68
RTNL_LINK_IP6_OUTPKTS
@ RTNL_LINK_IP6_OUTPKTS
Definition link.h:65
RTNL_LINK_IP6_OUTOCTETS
@ RTNL_LINK_IP6_OUTOCTETS
Definition link.h:80
RTNL_LINK_ICMP6_INERRORS
@ RTNL_LINK_ICMP6_INERRORS
Definition link.h:86
RTNL_LINK_IP6_FRAGFAILS
@ RTNL_LINK_IP6_FRAGFAILS
Definition link.h:73
RTNL_LINK_ICMP6_OUTMSGS
@ RTNL_LINK_ICMP6_OUTMSGS
Definition link.h:87
RTNL_LINK_IP6_CSUMERRORS
@ RTNL_LINK_IP6_CSUMERRORS
Definition link.h:90
RTNL_LINK_IP6_INUNKNOWNPROTOS
@ RTNL_LINK_IP6_INUNKNOWNPROTOS
Definition link.h:60
RTNL_LINK_ICMP6_CSUMERRORS
@ RTNL_LINK_ICMP6_CSUMERRORS
Definition link.h:89
RTNL_LINK_IP6_INPKTS
@ RTNL_LINK_IP6_INPKTS
Definition link.h:55
RTNL_LINK_IP6_CEPKTS
@ RTNL_LINK_IP6_CEPKTS
Definition link.h:94
RTNL_LINK_IP6_INBCASTPKTS
@ RTNL_LINK_IP6_INBCASTPKTS
Definition link.h:77
RTNL_LINK_IP6_INOCTETS
@ RTNL_LINK_IP6_INOCTETS
Definition link.h:79
RTNL_LINK_IP6_INHDRERRORS
@ RTNL_LINK_IP6_INHDRERRORS
Definition link.h:56
RTNL_LINK_IP6_REASMREQDS
@ RTNL_LINK_IP6_REASMREQDS
Definition link.h:69
RTNL_LINK_IP6_OUTFORWDATAGRAMS
@ RTNL_LINK_IP6_OUTFORWDATAGRAMS
Definition link.h:64
RTNL_LINK_IP6_INDISCARDS
@ RTNL_LINK_IP6_INDISCARDS
Definition link.h:62
RTNL_LINK_IP6_NOECTPKTS
@ RTNL_LINK_IP6_NOECTPKTS
Definition link.h:91
RTNL_LINK_IP6_OUTNOROUTES
@ RTNL_LINK_IP6_OUTNOROUTES
Definition link.h:67
RTNL_LINK_IP6_OUTDISCARDS
@ RTNL_LINK_IP6_OUTDISCARDS
Definition link.h:66
RTNL_LINK_IP6_FRAGCREATES
@ RTNL_LINK_IP6_FRAGCREATES
Definition link.h:74
RTNL_LINK_ICMP6_OUTERRORS
@ RTNL_LINK_ICMP6_OUTERRORS
Definition link.h:88
RTNL_LINK_IP6_INMCASTOCTETS
@ RTNL_LINK_IP6_INMCASTOCTETS
Definition link.h:81
RTNL_LINK_IP6_INADDRERRORS
@ RTNL_LINK_IP6_INADDRERRORS
Definition link.h:59
RTNL_LINK_IP6_ECT1PKTS
@ RTNL_LINK_IP6_ECT1PKTS
Definition link.h:92
RTNL_LINK_IP6_INTOOBIGERRORS
@ RTNL_LINK_IP6_INTOOBIGERRORS
Definition link.h:57
RTNL_LINK_IP6_OUTMCASTPKTS
@ RTNL_LINK_IP6_OUTMCASTPKTS
Definition link.h:76
RTNL_LINK_IP6_OUTBCASTPKTS
@ RTNL_LINK_IP6_OUTBCASTPKTS
Definition link.h:78
RTNL_LINK_IP6_FRAGOKS
@ RTNL_LINK_IP6_FRAGOKS
Definition link.h:72
RTNL_LINK_IP6_REASMFAILS
@ RTNL_LINK_IP6_REASMFAILS
Definition link.h:71
nl_size2str
char * nl_size2str(const size_t size, char *buf, const size_t len)
Convert a size toa character string.
Definition utils.c:411
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
nl_cancel_down_bytes
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
Definition utils.c:223
nl_msec2str
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
Definition utils.c:648
NL_DUMP_STATS
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition types.h:22
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
inet6_data
Definition inet6.c:23
nl_dump_params
Dumping parameters.
Definition types.h:32
nla_policy
Attribute validation policy.
Definition attr.h:63
nla_policy::type
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65
rtnl_link_af_ops
Available operations to modules implementing a link address family.
Definition link-api.h:76
rtnl_link_af_ops::ao_family
const unsigned int ao_family
The address family this operations set implements.
Definition link-api.h:78
rtnl_link
Link object.
Definition nl-route.h:29