Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
0002 
0003 /*
0004  * NETLINK      Netlink attributes
0005  *
0006  * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
0007  */
0008 
0009 #ifndef __LIBBPF_NLATTR_H
0010 #define __LIBBPF_NLATTR_H
0011 
0012 #include <stdint.h>
0013 #include <string.h>
0014 #include <errno.h>
0015 #include <linux/netlink.h>
0016 #include <linux/rtnetlink.h>
0017 
0018 /* avoid multiple definition of netlink features */
0019 #define __LINUX_NETLINK_H
0020 
0021 /**
0022  * Standard attribute types to specify validation policy
0023  */
0024 enum {
0025     LIBBPF_NLA_UNSPEC,  /**< Unspecified type, binary data chunk */
0026     LIBBPF_NLA_U8,      /**< 8 bit integer */
0027     LIBBPF_NLA_U16,     /**< 16 bit integer */
0028     LIBBPF_NLA_U32,     /**< 32 bit integer */
0029     LIBBPF_NLA_U64,     /**< 64 bit integer */
0030     LIBBPF_NLA_STRING,  /**< NUL terminated character string */
0031     LIBBPF_NLA_FLAG,    /**< Flag */
0032     LIBBPF_NLA_MSECS,   /**< Micro seconds (64bit) */
0033     LIBBPF_NLA_NESTED,  /**< Nested attributes */
0034     __LIBBPF_NLA_TYPE_MAX,
0035 };
0036 
0037 #define LIBBPF_NLA_TYPE_MAX (__LIBBPF_NLA_TYPE_MAX - 1)
0038 
0039 /**
0040  * @ingroup attr
0041  * Attribute validation policy.
0042  *
0043  * See section @core_doc{core_attr_parse,Attribute Parsing} for more details.
0044  */
0045 struct libbpf_nla_policy {
0046     /** Type of attribute or LIBBPF_NLA_UNSPEC */
0047     uint16_t    type;
0048 
0049     /** Minimal length of payload required */
0050     uint16_t    minlen;
0051 
0052     /** Maximal length of payload allowed */
0053     uint16_t    maxlen;
0054 };
0055 
0056 struct libbpf_nla_req {
0057     struct nlmsghdr nh;
0058     union {
0059         struct ifinfomsg ifinfo;
0060         struct tcmsg tc;
0061     };
0062     char buf[128];
0063 };
0064 
0065 /**
0066  * @ingroup attr
0067  * Iterate over a stream of attributes
0068  * @arg pos loop counter, set to current attribute
0069  * @arg head    head of attribute stream
0070  * @arg len length of attribute stream
0071  * @arg rem initialized to len, holds bytes currently remaining in stream
0072  */
0073 #define libbpf_nla_for_each_attr(pos, head, len, rem) \
0074     for (pos = head, rem = len; \
0075          nla_ok(pos, rem); \
0076          pos = nla_next(pos, &(rem)))
0077 
0078 /**
0079  * libbpf_nla_data - head of payload
0080  * @nla: netlink attribute
0081  */
0082 static inline void *libbpf_nla_data(const struct nlattr *nla)
0083 {
0084     return (void *)nla + NLA_HDRLEN;
0085 }
0086 
0087 static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla)
0088 {
0089     return *(uint8_t *)libbpf_nla_data(nla);
0090 }
0091 
0092 static inline uint32_t libbpf_nla_getattr_u32(const struct nlattr *nla)
0093 {
0094     return *(uint32_t *)libbpf_nla_data(nla);
0095 }
0096 
0097 static inline const char *libbpf_nla_getattr_str(const struct nlattr *nla)
0098 {
0099     return (const char *)libbpf_nla_data(nla);
0100 }
0101 
0102 /**
0103  * libbpf_nla_len - length of payload
0104  * @nla: netlink attribute
0105  */
0106 static inline int libbpf_nla_len(const struct nlattr *nla)
0107 {
0108     return nla->nla_len - NLA_HDRLEN;
0109 }
0110 
0111 int libbpf_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head,
0112              int len, struct libbpf_nla_policy *policy);
0113 int libbpf_nla_parse_nested(struct nlattr *tb[], int maxtype,
0114                 struct nlattr *nla,
0115                 struct libbpf_nla_policy *policy);
0116 
0117 int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh);
0118 
0119 static inline struct nlattr *nla_data(struct nlattr *nla)
0120 {
0121     return (struct nlattr *)((void *)nla + NLA_HDRLEN);
0122 }
0123 
0124 static inline struct nlattr *req_tail(struct libbpf_nla_req *req)
0125 {
0126     return (struct nlattr *)((void *)req + NLMSG_ALIGN(req->nh.nlmsg_len));
0127 }
0128 
0129 static inline int nlattr_add(struct libbpf_nla_req *req, int type,
0130                  const void *data, int len)
0131 {
0132     struct nlattr *nla;
0133 
0134     if (NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > sizeof(*req))
0135         return -EMSGSIZE;
0136     if (!!data != !!len)
0137         return -EINVAL;
0138 
0139     nla = req_tail(req);
0140     nla->nla_type = type;
0141     nla->nla_len = NLA_HDRLEN + len;
0142     if (data)
0143         memcpy(nla_data(nla), data, len);
0144     req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(nla->nla_len);
0145     return 0;
0146 }
0147 
0148 static inline struct nlattr *nlattr_begin_nested(struct libbpf_nla_req *req, int type)
0149 {
0150     struct nlattr *tail;
0151 
0152     tail = req_tail(req);
0153     if (nlattr_add(req, type | NLA_F_NESTED, NULL, 0))
0154         return NULL;
0155     return tail;
0156 }
0157 
0158 static inline void nlattr_end_nested(struct libbpf_nla_req *req,
0159                      struct nlattr *tail)
0160 {
0161     tail->nla_len = (void *)req_tail(req) - (void *)tail;
0162 }
0163 
0164 #endif /* __LIBBPF_NLATTR_H */