162306a36Sopenharmony_ci/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * NETLINK Netlink attributes 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef __LIBBPF_NLATTR_H 1062306a36Sopenharmony_ci#define __LIBBPF_NLATTR_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <stdint.h> 1362306a36Sopenharmony_ci#include <string.h> 1462306a36Sopenharmony_ci#include <errno.h> 1562306a36Sopenharmony_ci#include <linux/netlink.h> 1662306a36Sopenharmony_ci#include <linux/rtnetlink.h> 1762306a36Sopenharmony_ci#include <linux/genetlink.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* avoid multiple definition of netlink features */ 2062306a36Sopenharmony_ci#define __LINUX_NETLINK_H 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/** 2362306a36Sopenharmony_ci * Standard attribute types to specify validation policy 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_cienum { 2662306a36Sopenharmony_ci LIBBPF_NLA_UNSPEC, /**< Unspecified type, binary data chunk */ 2762306a36Sopenharmony_ci LIBBPF_NLA_U8, /**< 8 bit integer */ 2862306a36Sopenharmony_ci LIBBPF_NLA_U16, /**< 16 bit integer */ 2962306a36Sopenharmony_ci LIBBPF_NLA_U32, /**< 32 bit integer */ 3062306a36Sopenharmony_ci LIBBPF_NLA_U64, /**< 64 bit integer */ 3162306a36Sopenharmony_ci LIBBPF_NLA_STRING, /**< NUL terminated character string */ 3262306a36Sopenharmony_ci LIBBPF_NLA_FLAG, /**< Flag */ 3362306a36Sopenharmony_ci LIBBPF_NLA_MSECS, /**< Micro seconds (64bit) */ 3462306a36Sopenharmony_ci LIBBPF_NLA_NESTED, /**< Nested attributes */ 3562306a36Sopenharmony_ci __LIBBPF_NLA_TYPE_MAX, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/** 4162306a36Sopenharmony_ci * @ingroup attr 4262306a36Sopenharmony_ci * Attribute validation policy. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * See section @core_doc{core_attr_parse,Attribute Parsing} for more details. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_cistruct libbpf_nla_policy { 4762306a36Sopenharmony_ci /** Type of attribute or LIBBPF_NLA_UNSPEC */ 4862306a36Sopenharmony_ci uint16_t type; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /** Minimal length of payload required */ 5162306a36Sopenharmony_ci uint16_t minlen; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /** Maximal length of payload allowed */ 5462306a36Sopenharmony_ci uint16_t maxlen; 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistruct libbpf_nla_req { 5862306a36Sopenharmony_ci struct nlmsghdr nh; 5962306a36Sopenharmony_ci union { 6062306a36Sopenharmony_ci struct ifinfomsg ifinfo; 6162306a36Sopenharmony_ci struct tcmsg tc; 6262306a36Sopenharmony_ci struct genlmsghdr gnl; 6362306a36Sopenharmony_ci }; 6462306a36Sopenharmony_ci char buf[128]; 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/** 6862306a36Sopenharmony_ci * @ingroup attr 6962306a36Sopenharmony_ci * Iterate over a stream of attributes 7062306a36Sopenharmony_ci * @arg pos loop counter, set to current attribute 7162306a36Sopenharmony_ci * @arg head head of attribute stream 7262306a36Sopenharmony_ci * @arg len length of attribute stream 7362306a36Sopenharmony_ci * @arg rem initialized to len, holds bytes currently remaining in stream 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci#define libbpf_nla_for_each_attr(pos, head, len, rem) \ 7662306a36Sopenharmony_ci for (pos = head, rem = len; \ 7762306a36Sopenharmony_ci nla_ok(pos, rem); \ 7862306a36Sopenharmony_ci pos = nla_next(pos, &(rem))) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/** 8162306a36Sopenharmony_ci * libbpf_nla_data - head of payload 8262306a36Sopenharmony_ci * @nla: netlink attribute 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistatic inline void *libbpf_nla_data(const struct nlattr *nla) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return (void *)nla + NLA_HDRLEN; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci return *(uint8_t *)libbpf_nla_data(nla); 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic inline uint16_t libbpf_nla_getattr_u16(const struct nlattr *nla) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci return *(uint16_t *)libbpf_nla_data(nla); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return *(uint32_t *)libbpf_nla_data(nla); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline uint64_t libbpf_nla_getattr_u64(const struct nlattr *nla) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci return *(uint64_t *)libbpf_nla_data(nla); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic inline const char *libbpf_nla_getattr_str(const struct nlattr *nla) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci return (const char *)libbpf_nla_data(nla); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * libbpf_nla_len - length of payload 11662306a36Sopenharmony_ci * @nla: netlink attribute 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_cistatic inline int libbpf_nla_len(const struct nlattr *nla) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci return nla->nla_len - NLA_HDRLEN; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciint libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 12462306a36Sopenharmony_ci int len, struct libbpf_nla_policy *policy); 12562306a36Sopenharmony_ciint libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype, 12662306a36Sopenharmony_ci struct nlattr *nla, 12762306a36Sopenharmony_ci struct libbpf_nla_policy *policy); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciint libbpf_nla_dump_errormsg(struct nlmsghdr *nlh); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic inline struct nlattr *nla_data(struct nlattr *nla) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci return (struct nlattr *)((void *)nla + NLA_HDRLEN); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic inline struct nlattr *req_tail(struct libbpf_nla_req *req) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci return (struct nlattr *)((void *)req + NLMSG_ALIGN(req->nh.nlmsg_len)); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic inline int nlattr_add(struct libbpf_nla_req *req, int type, 14262306a36Sopenharmony_ci const void *data, int len) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct nlattr *nla; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > sizeof(*req)) 14762306a36Sopenharmony_ci return -EMSGSIZE; 14862306a36Sopenharmony_ci if (!!data != !!len) 14962306a36Sopenharmony_ci return -EINVAL; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci nla = req_tail(req); 15262306a36Sopenharmony_ci nla->nla_type = type; 15362306a36Sopenharmony_ci nla->nla_len = NLA_HDRLEN + len; 15462306a36Sopenharmony_ci if (data) 15562306a36Sopenharmony_ci memcpy(nla_data(nla), data, len); 15662306a36Sopenharmony_ci req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(nla->nla_len); 15762306a36Sopenharmony_ci return 0; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic inline struct nlattr *nlattr_begin_nested(struct libbpf_nla_req *req, int type) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct nlattr *tail; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci tail = req_tail(req); 16562306a36Sopenharmony_ci if (nlattr_add(req, type | NLA_F_NESTED, NULL, 0)) 16662306a36Sopenharmony_ci return NULL; 16762306a36Sopenharmony_ci return tail; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic inline void nlattr_end_nested(struct libbpf_nla_req *req, 17162306a36Sopenharmony_ci struct nlattr *tail) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci tail->nla_len = (void *)req_tail(req) - (void *)tail; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#endif /* __LIBBPF_NLATTR_H */ 177