6#include <netlink-private/netlink.h> 
    7#include <netlink/netlink.h> 
    8#include <netlink/attr.h> 
    9#include <netlink/route/rtnl.h> 
   10#include <netlink/route/link/inet6.h> 
   11#include <netlink-private/route/link/api.h> 
   13#include "netlink-private/route/utils.h" 
   14#include "netlink-private/utils.h" 
   16#define I6_ADDR_GEN_MODE_UNKNOWN        UINT8_MAX 
   21        struct ifla_cacheinfo   i6_cacheinfo;
 
   22        uint32_t                i6_conf[DEVCONF_MAX];
 
   23        struct in6_addr         i6_token;
 
   24        uint8_t                 i6_addr_gen_mode;
 
   27static void *inet6_alloc(
struct rtnl_link *link)
 
   33                i6->i6_addr_gen_mode = I6_ADDR_GEN_MODE_UNKNOWN;
 
   38static void *inet6_clone(
struct rtnl_link *link, 
void *data)
 
   42        if ((i6 = inet6_alloc(link)))
 
   43                memcpy(i6, data, 
sizeof(*i6));
 
   48static void inet6_free(
struct rtnl_link *link, 
void *data)
 
   53static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = {
 
   55        [IFLA_INET6_CACHEINFO]          = { .minlen = 
sizeof(
struct ifla_cacheinfo) },
 
   56        [IFLA_INET6_CONF]               = { .minlen = 4 },
 
   57        [IFLA_INET6_STATS]              = { .minlen = 8 },
 
   58        [IFLA_INET6_ICMP6STATS]         = { .minlen = 8 },
 
   59        [IFLA_INET6_TOKEN]              = { .minlen = 
sizeof(
struct in6_addr) },
 
   60        [IFLA_INET6_ADDR_GEN_MODE]      = { .type = 
NLA_U8 },
 
   63static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = {
 
  101static const uint8_t map_stat_id_from_IPSTATS_MIB_v2[__IPSTATS_MIB_MAX] = {
 
  142const uint8_t *
const _nltst_map_stat_id_from_IPSTATS_MIB_v2 = map_stat_id_from_IPSTATS_MIB_v2;
 
  144static int inet6_parse_protinfo(
struct rtnl_link *link, 
struct nlattr *attr,
 
  148        struct nlattr *tb[IFLA_INET6_MAX+1];
 
  154        if (tb[IFLA_INET6_CONF] && 
nla_len(tb[IFLA_INET6_CONF]) % 4)
 
  156        if (tb[IFLA_INET6_STATS] && 
nla_len(tb[IFLA_INET6_STATS]) % 8)
 
  158        if (tb[IFLA_INET6_ICMP6STATS] && 
nla_len(tb[IFLA_INET6_ICMP6STATS]) % 8)
 
  161        if (tb[IFLA_INET6_FLAGS])
 
  164        if (tb[IFLA_INET6_CACHEINFO])
 
  165                nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
 
  166                           sizeof(i6->i6_cacheinfo));
 
  168        if (tb[IFLA_INET6_CONF])
 
  170                           sizeof(i6->i6_conf));
 
  172        if (tb[IFLA_INET6_TOKEN])
 
  173                nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN],
 
  174                           sizeof(
struct in6_addr));
 
  176        if (tb[IFLA_INET6_ADDR_GEN_MODE])
 
  177                i6->i6_addr_gen_mode = 
nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]);
 
  183        if (tb[IFLA_INET6_STATS]) {
 
  184                unsigned char *cnt = 
nla_data(tb[IFLA_INET6_STATS]);
 
  187                int len = 
nla_len(tb[IFLA_INET6_STATS]) / 8;
 
  188                const uint8_t *map_stat_id = map_stat_id_from_IPSTATS_MIB_v2;
 
  191                    (tb[IFLA_INET6_ICMP6STATS] && 
nla_len(tb[IFLA_INET6_ICMP6STATS]) < 6)) {
 
  197                        map_stat_id = map_stat_id_from_IPSTATS_MIB_v1;
 
  200                len = min_t(
int, __IPSTATS_MIB_MAX, len);
 
  201                for (i = 1; i < len; i++) {
 
  202                        memcpy(&stat, &cnt[i * 
sizeof(stat)], 
sizeof(stat));
 
  207        if (tb[IFLA_INET6_ICMP6STATS]) {
 
  208                unsigned char *cnt = 
nla_data(tb[IFLA_INET6_ICMP6STATS]);
 
  211                int len = min_t(
int, __ICMP6_MIB_MAX, 
nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
 
  213                _NL_STATIC_ASSERT (__ICMP6_MIB_MAX == 6);
 
  216                for (i = 1; i < len; i++) {
 
  217                        memcpy(&stat, &cnt[i * 
sizeof(stat)], 
sizeof(stat));
 
  226static int inet6_fill_af(
struct rtnl_link *link, 
struct nl_msg *msg, 
void *data)
 
  230        if (id->i6_addr_gen_mode != I6_ADDR_GEN_MODE_UNKNOWN)
 
  231                NLA_PUT_U8(msg, IFLA_INET6_ADDR_GEN_MODE, id->i6_addr_gen_mode);
 
  240#define IF_RA_OTHERCONF 0x80 
  241#define IF_RA_MANAGED   0x40 
  242#define IF_RA_RCVD      0x20 
  243#define IF_RS_SENT      0x10 
  244#define IF_READY        0x80000000 
  246static const struct trans_tbl inet6_flags[] = {
 
  247        __ADD(IF_RA_OTHERCONF, ra_otherconf),
 
  248        __ADD(IF_RA_MANAGED, ra_managed),
 
  249        __ADD(IF_RA_RCVD, ra_rcvd),
 
  250        __ADD(IF_RS_SENT, rs_sent),
 
  251        __ADD(IF_READY, ready),
 
  254char *rtnl_link_inet6_flags2str(
int flags, 
char *buf, 
size_t len)
 
  256        return __flags2str(flags, buf, len, inet6_flags,
 
  257                           ARRAY_SIZE(inet6_flags));
 
  260int rtnl_link_inet6_str2flags(
const char *name)
 
  262        return __str2flags(name, inet6_flags, ARRAY_SIZE(inet6_flags));
 
  265static const struct trans_tbl inet6_devconf[] = {
 
  266        __ADD(DEVCONF_FORWARDING, forwarding),
 
  267        __ADD(DEVCONF_HOPLIMIT, hoplimit),
 
  268        __ADD(DEVCONF_MTU6, mtu6),
 
  269        __ADD(DEVCONF_ACCEPT_RA, accept_ra),
 
  270        __ADD(DEVCONF_ACCEPT_REDIRECTS, accept_redirects),
 
  271        __ADD(DEVCONF_AUTOCONF, autoconf),
 
  272        __ADD(DEVCONF_DAD_TRANSMITS, dad_transmits),
 
  273        __ADD(DEVCONF_RTR_SOLICITS, rtr_solicits),
 
  274        __ADD(DEVCONF_RTR_SOLICIT_INTERVAL, rtr_solicit_interval),
 
  275        __ADD(DEVCONF_RTR_SOLICIT_DELAY, rtr_solicit_delay),
 
  276        __ADD(DEVCONF_USE_TEMPADDR, use_tempaddr),
 
  277        __ADD(DEVCONF_TEMP_VALID_LFT, temp_valid_lft),
 
  278        __ADD(DEVCONF_TEMP_PREFERED_LFT, temp_prefered_lft),
 
  279        __ADD(DEVCONF_REGEN_MAX_RETRY, regen_max_retry),
 
  280        __ADD(DEVCONF_MAX_DESYNC_FACTOR, max_desync_factor),
 
  281        __ADD(DEVCONF_MAX_ADDRESSES, max_addresses),
 
  282        __ADD(DEVCONF_FORCE_MLD_VERSION, force_mld_version),
 
  283        __ADD(DEVCONF_ACCEPT_RA_DEFRTR, accept_ra_defrtr),
 
  284        __ADD(DEVCONF_ACCEPT_RA_PINFO, accept_ra_pinfo),
 
  285        __ADD(DEVCONF_ACCEPT_RA_RTR_PREF, accept_ra_rtr_pref),
 
  286        __ADD(DEVCONF_RTR_PROBE_INTERVAL, rtr_probe_interval),
 
  287        __ADD(DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, accept_ra_rt_info),
 
  288        __ADD(DEVCONF_PROXY_NDP, proxy_ndp),
 
  289        __ADD(DEVCONF_OPTIMISTIC_DAD, optimistic_dad),
 
  290        __ADD(DEVCONF_ACCEPT_SOURCE_ROUTE, accept_source_route),
 
  291        __ADD(DEVCONF_MC_FORWARDING, mc_forwarding),
 
  292        __ADD(DEVCONF_DISABLE_IPV6, disable_ipv6),
 
  293        __ADD(DEVCONF_ACCEPT_DAD, accept_dad),
 
  294        __ADD(DEVCONF_FORCE_TLLAO, force_tllao),
 
  297static char *inet6_devconf2str(
int type, 
char *buf, 
size_t len)
 
  299        return __type2str(type, buf, len, inet6_devconf,
 
  300                          ARRAY_SIZE(inet6_devconf));
 
  303static const struct trans_tbl inet6_addr_gen_mode[] = {
 
  304        __ADD(IN6_ADDR_GEN_MODE_EUI64, eui64),
 
  305        __ADD(IN6_ADDR_GEN_MODE_NONE, none),
 
  306        __ADD(IN6_ADDR_GEN_MODE_STABLE_PRIVACY, stable_privacy),
 
  309const char *rtnl_link_inet6_addrgenmode2str(uint8_t mode, 
char *buf, 
size_t len)
 
  311        return __type2str(mode, buf, len, inet6_addr_gen_mode,
 
  312                          ARRAY_SIZE(inet6_addr_gen_mode));
 
  315uint8_t rtnl_link_inet6_str2addrgenmode(
const char *mode)
 
  317        return (uint8_t) __str2type(mode, inet6_addr_gen_mode,
 
  318                                    ARRAY_SIZE(inet6_addr_gen_mode));
 
  321static void inet6_dump_details(
struct rtnl_link *link,
 
  325        struct nl_addr *addr;
 
  329        nl_dump_line(p, 
"    ipv6 max-reasm-len %s",
 
  330                     nl_size2str(i6->i6_cacheinfo.max_reasm_len, buf, 
sizeof(buf)));
 
  333                rtnl_link_inet6_flags2str(i6->i6_flags, buf, 
sizeof(buf)));
 
  335        nl_dump_line(p, 
"      create-stamp %.2fs reachable-time %s",
 
  336                     (
double) i6->i6_cacheinfo.tstamp / 100.,
 
  337                     nl_msec2str(i6->i6_cacheinfo.reachable_time, buf, 
sizeof(buf)));
 
  339        nl_dump(p, 
" retrans-time %s\n",
 
  340                nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, 
sizeof(buf)));
 
  342        addr = 
nl_addr_build(AF_INET6, &i6->i6_token, 
sizeof(i6->i6_token));
 
  347        nl_dump(p, 
"      link-local address mode %s\n",
 
  348                rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode,
 
  351        nl_dump_line(p, 
"      devconf:\n");
 
  352        nl_dump_line(p, 
"      ");
 
  354        for (i = 0; i < DEVCONF_MAX; i++) {
 
  356                uint32_t value = i6->i6_conf[i];
 
  360                case DEVCONF_TEMP_VALID_LFT:
 
  361                case DEVCONF_TEMP_PREFERED_LFT:
 
  362                        nl_msec2str((uint64_t) value * 1000., buf2, 
sizeof(buf2));
 
  365                case DEVCONF_RTR_PROBE_INTERVAL:
 
  366                case DEVCONF_RTR_SOLICIT_INTERVAL:
 
  367                case DEVCONF_RTR_SOLICIT_DELAY:
 
  372                        snprintf(buf2, 
sizeof(buf2), 
"%u", value);
 
  376                inet6_devconf2str(i, buf, 
sizeof(buf));
 
  378                offset = 23 - strlen(buf2);
 
  382                for (x = strlen(buf); x < offset; x++)
 
  385                _nl_strncpy_trunc(&buf[offset], buf2, 
sizeof(buf) - offset);
 
  387                nl_dump_line(p, 
"%s", buf);
 
  391                        nl_dump_line(p, 
"      ");
 
  401static void inet6_dump_stats(
struct rtnl_link *link,
 
  407        nl_dump(p, 
"    IPv6:       InPkts           InOctets     " 
  408                   "    InDiscards         InDelivers\n");
 
  414                nl_dump(p, 
"%14.2f %3s ", octets, octetsUnit);
 
  418        nl_dump(p, 
"%18" PRIu64 
" %18" PRIu64 
"\n",
 
  422        nl_dump(p, 
"               OutPkts          OutOctets     " 
  423                   "   OutDiscards        OutForwards\n");
 
  430                nl_dump(p, 
"%14.2f %3s ", octets, octetsUnit);
 
  434        nl_dump(p, 
"%18" PRIu64 
" %18" PRIu64 
"\n",
 
  438        nl_dump(p, 
"           InMcastPkts      InMcastOctets     " 
  439                   "   InBcastPkts     InBcastOctests\n");
 
  446                nl_dump(p, 
"%14.2f %3s ", octets, octetsUnit);
 
  454                nl_dump(p, 
"%14.2f %3s\n", octets, octetsUnit);
 
  458        nl_dump(p, 
"          OutMcastPkts     OutMcastOctets     " 
  459                   "  OutBcastPkts    OutBcastOctests\n");
 
  466                nl_dump(p, 
"%14.2f %3s ", octets, octetsUnit);
 
  474                nl_dump(p, 
"%14.2f %3s\n", octets, octetsUnit);
 
  478        nl_dump(p, 
"              ReasmOKs         ReasmFails     " 
  479                   "    ReasmReqds       ReasmTimeout\n");
 
  480        nl_dump(p, 
"    %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
"\n",
 
  486        nl_dump(p, 
"               FragOKs          FragFails    " 
  488        nl_dump(p, 
"    %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
"\n",
 
  493        nl_dump(p, 
"           InHdrErrors      InTooBigErrors   " 
  494                   "     InNoRoutes       InAddrErrors\n");
 
  495        nl_dump(p, 
"    %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
"\n",
 
  501        nl_dump(p, 
"       InUnknownProtos     InTruncatedPkts   " 
  502                   "    OutNoRoutes       InCsumErrors\n");
 
  503        nl_dump(p, 
"    %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
"\n",
 
  509        nl_dump(p, 
"           InNoECTPkts          InECT1Pkts   " 
  510                   "     InECT0Pkts           InCEPkts\n");
 
  511        nl_dump(p, 
"    %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
"\n",
 
  517        nl_dump(p, 
"    ICMPv6:     InMsgs           InErrors        " 
  518                   "    OutMsgs          OutErrors       InCsumErrors\n");
 
  519        nl_dump(p, 
"    %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
" %18" PRIu64 
"\n",
 
  527static const struct nla_policy protinfo_policy = {
 
  531static struct rtnl_link_af_ops inet6_ops = {
 
  532        .ao_family                      = AF_INET6,
 
  533        .ao_alloc                       = &inet6_alloc,
 
  534        .ao_clone                       = &inet6_clone,
 
  535        .ao_free                        = &inet6_free,
 
  536        .ao_parse_protinfo              = &inet6_parse_protinfo,
 
  537        .ao_parse_af                    = &inet6_parse_protinfo,
 
  538        .ao_fill_af                     = &inet6_fill_af,
 
  541        .ao_protinfo_policy             = &protinfo_policy,
 
  554int rtnl_link_inet6_get_flags(
struct rtnl_link *link, uint32_t* out_flags)
 
  561        *out_flags = 
id->i6_flags;
 
  575int rtnl_link_inet6_set_flags(
struct rtnl_link *link, uint32_t flags)
 
  582        id->i6_flags = flags;
 
  598int rtnl_link_inet6_get_token(
struct rtnl_link *link, 
struct nl_addr **addr)
 
  605        *addr = 
nl_addr_build(AF_INET6, &id->i6_token, 
sizeof(id->i6_token));
 
  628int rtnl_link_inet6_set_token(
struct rtnl_link *link, 
struct nl_addr *addr)
 
  640               sizeof(id->i6_token));
 
  657int rtnl_link_inet6_get_addr_gen_mode(
struct rtnl_link *link, uint8_t *mode)
 
  664        if (id->i6_addr_gen_mode == I6_ADDR_GEN_MODE_UNKNOWN)
 
  667        *mode = 
id->i6_addr_gen_mode;
 
  681int rtnl_link_inet6_set_addr_gen_mode(
struct rtnl_link *link, uint8_t mode)
 
  688        id->i6_addr_gen_mode = mode;
 
  692static void __init inet6_init(
void)
 
  697static void __exit inet6_exit(
void)
 
int nl_addr_iszero(const struct nl_addr *addr)
Returns true if the address consists of all zeros.
 
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
 
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
 
int nl_addr_get_family(const struct nl_addr *addr)
Return address family.
 
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
 
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
 
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
 
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
 
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
 
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
 
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
 
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
 
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
 
int nla_len(const struct nlattr *nla)
Return length of the payload .
 
@ NLA_NESTED
Nested attributes.
 
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.
 
int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
Unregister operations for a link address family.
 
int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
Register operations for a link address family.
 
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.
 
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.
 
@ RTNL_LINK_IP6_INBCASTOCTETS
 
@ RTNL_LINK_REASM_OVERLAPS
 
@ RTNL_LINK_IP6_INTRUNCATEDPKTS
 
@ RTNL_LINK_IP6_INNOROUTES
 
@ RTNL_LINK_IP6_OUTMCASTOCTETS
 
@ RTNL_LINK_IP6_INMCASTPKTS
 
@ RTNL_LINK_IP6_OUTBCASTOCTETS
 
@ RTNL_LINK_IP6_INDELIVERS
 
@ RTNL_LINK_IP6_REASMTIMEOUT
 
@ RTNL_LINK_IP6_OUTOCTETS
 
@ RTNL_LINK_ICMP6_INERRORS
 
@ RTNL_LINK_IP6_FRAGFAILS
 
@ RTNL_LINK_ICMP6_OUTMSGS
 
@ RTNL_LINK_IP6_CSUMERRORS
 
@ RTNL_LINK_IP6_INUNKNOWNPROTOS
 
@ RTNL_LINK_ICMP6_CSUMERRORS
 
@ RTNL_LINK_IP6_INBCASTPKTS
 
@ RTNL_LINK_IP6_INHDRERRORS
 
@ RTNL_LINK_IP6_REASMREQDS
 
@ RTNL_LINK_IP6_OUTFORWDATAGRAMS
 
@ RTNL_LINK_IP6_INDISCARDS
 
@ RTNL_LINK_IP6_NOECTPKTS
 
@ RTNL_LINK_IP6_OUTNOROUTES
 
@ RTNL_LINK_IP6_OUTDISCARDS
 
@ RTNL_LINK_IP6_FRAGCREATES
 
@ RTNL_LINK_ICMP6_OUTERRORS
 
@ RTNL_LINK_IP6_INMCASTOCTETS
 
@ RTNL_LINK_IP6_INADDRERRORS
 
@ RTNL_LINK_IP6_INTOOBIGERRORS
 
@ RTNL_LINK_IP6_OUTMCASTPKTS
 
@ RTNL_LINK_IP6_OUTBCASTPKTS
 
@ RTNL_LINK_IP6_REASMFAILS
 
char * nl_size2str(const size_t size, char *buf, const size_t len)
Convert a size toa character string.
 
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
 
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
 
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
 
@ NL_DUMP_STATS
Dump all attributes including statistics.
 
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
 
Attribute validation policy.
 
uint16_t type
Type of attribute or NLA_UNSPEC.