161 #include <netlink-local.h>
162 #include <netlink/netlink.h>
163 #include <netlink/utils.h>
164 #include <netlink/cache.h>
165 #include <netlink/attr.h>
166 #include <linux/socket.h>
168 static size_t default_msg_size;
170 static void __init init_msg_size(
void)
172 default_msg_size = getpagesize();
186 return NLMSG_HDRLEN + payload;
220 return (
unsigned char *) nlh + NLMSG_HDRLEN;
223 void *nlmsg_tail(
const struct nlmsghdr *nlh)
225 return (
unsigned char *) nlh + NLMSG_ALIGN(nlh->
nlmsg_len);
252 return (
struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
262 return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
272 int nlmsg_valid_hdr(
const struct nlmsghdr *nlh,
int hdrlen)
287 return (remaining >=
sizeof(
struct nlmsghdr) &&
302 int totlen = NLMSG_ALIGN(nlh->
nlmsg_len);
304 *remaining -= totlen;
306 return (
struct nlmsghdr *) ((
unsigned char *) nlh + totlen);
322 if (!nlmsg_valid_hdr(nlh, hdrlen))
323 return nl_errno(EINVAL);
353 if (!nlmsg_valid_hdr(nlh, hdrlen))
354 return nl_errno(EINVAL);
367 static struct nl_msg *__nlmsg_alloc(
size_t len)
371 nm = calloc(1,
sizeof(*nm));
375 nm->nm_nlh = calloc(1, len);
379 nm->nm_protocol = -1;
383 NL_DBG(2,
"msg %p: Allocated new message, maxlen=%zu\n", nm, len);
403 return __nlmsg_alloc(default_msg_size);
411 return __nlmsg_alloc(max);
453 .nlmsg_flags = flags,
458 NL_DBG(2,
"msg %p: Allocated new simple message\n", msg);
472 default_msg_size = max;
488 nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->
nlmsg_len));
514 void *buf = n->nm_nlh;
518 if (len > n->nm_size)
521 tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
523 if ((tlen + nlmsg_len) > n->nm_size) {
529 n->nm_nlh->nlmsg_len += tlen;
532 memset(buf + len, 0, tlen - len);
534 NL_DBG(2,
"msg %p: Reserved %zu bytes, pad=%d, nlmsg_len=%d\n",
535 n, len, pad, n->nm_nlh->nlmsg_len);
558 return nl_errno(ENOMEM);
560 memcpy(tmp, data, len);
561 NL_DBG(2,
"msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
584 if (newlen <= n->nm_size)
585 return nl_errno(EINVAL);
587 tmp = realloc(n->nm_nlh, newlen);
589 return nl_errno(ENOMEM);
614 int type,
int payload,
int flags)
618 if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
621 nlh = (
struct nlmsghdr *) n->nm_nlh;
627 NL_DBG(2,
"msg %p: Added netlink header type=%d, flags=%d, pid=%d, "
628 "seq=%d\n", n, type, flags, pid, seq);
666 NL_DBG(2,
"msg %p: Freed\n", n);
676 void nlmsg_set_proto(
struct nl_msg *msg,
int protocol)
678 msg->nm_protocol = protocol;
681 int nlmsg_get_proto(
struct nl_msg *msg)
683 return msg->nm_protocol;
686 size_t nlmsg_get_max_size(
struct nl_msg *msg)
691 void nlmsg_set_src(
struct nl_msg *msg,
struct sockaddr_nl *addr)
693 memcpy(&msg->nm_src, addr,
sizeof(*addr));
696 struct sockaddr_nl *nlmsg_get_src(
struct nl_msg *msg)
701 void nlmsg_set_dst(
struct nl_msg *msg,
struct sockaddr_nl *addr)
703 memcpy(&msg->nm_dst, addr,
sizeof(*addr));
706 struct sockaddr_nl *nlmsg_get_dst(
struct nl_msg *msg)
711 void nlmsg_set_creds(
struct nl_msg *msg,
struct ucred *creds)
713 memcpy(&msg->nm_creds, creds,
sizeof(*creds));
714 msg->nm_flags |= NL_MSG_CRED_PRESENT;
717 struct ucred *nlmsg_get_creds(
struct nl_msg *msg)
719 if (msg->nm_flags & NL_MSG_CRED_PRESENT)
720 return &msg->nm_creds;
731 static struct trans_tbl nl_msgtypes[] = {
738 char *nl_nlmsgtype2str(
int type,
char *buf,
size_t size)
740 return __type2str(type, buf, size, nl_msgtypes,
741 ARRAY_SIZE(nl_msgtypes));
744 int nl_str2nlmsgtype(
const char *name)
746 return __str2type(name, nl_msgtypes, ARRAY_SIZE(nl_msgtypes));
756 char *nl_nlmsg_flags2str(
int flags,
char *buf,
size_t len)
760 #define PRINT_FLAG(f) \
761 if (flags & NLM_F_##f) { \
762 flags &= ~NLM_F_##f; \
763 strncat(buf, #f, len - strlen(buf) - 1); \
765 strncat(buf, ",", len - strlen(buf) - 1); \
782 snprintf(s,
sizeof(s),
"0x%x", flags);
783 strncat(buf, s, len - strlen(buf) - 1);
799 void (*cb)(
struct nl_object *,
void *);
806 struct dp_xdata *x = p->pp_arg;
812 int nl_msg_parse(
struct nl_msg *msg,
void (*cb)(
struct nl_object *,
void *),
819 struct dp_xdata x = {
827 return nl_error(ENOENT,
"Unknown message type %d",
831 return nl_cache_parse(ops, NULL,
nlmsg_hdr(msg), &p);
841 static void prefix_line(FILE *ofd,
int prefix)
845 for (i = 0; i < prefix; i++)
849 static inline void dump_hex(FILE *ofd,
char *start,
int len,
int prefix)
852 char ascii[21] = {0};
854 limit = 18 - (prefix * 2);
855 prefix_line(ofd, prefix);
858 for (i = 0, a = 0, c = 0; i < len; i++) {
859 int v = *(uint8_t *) (start + i);
861 fprintf(ofd,
"%02x ", v);
862 ascii[a++] = isprint(v) ? v :
'.';
865 fprintf(ofd,
"%s\n", ascii);
867 prefix_line(ofd, prefix);
871 memset(ascii, 0,
sizeof(ascii));
877 for (i = 0; i < (limit - c); i++)
879 fprintf(ofd,
"%s\n", ascii);
883 static void print_hdr(FILE *ofd,
struct nl_msg *msg)
890 fprintf(ofd,
" .nlmsg_len = %d\n", nlh->
nlmsg_len);
898 snprintf(buf,
sizeof(buf),
"%s::%s", ops->co_name, mt->
mt_name);
900 nl_nlmsgtype2str(nlh->
nlmsg_type, buf,
sizeof(buf));
902 fprintf(ofd,
" .nlmsg_type = %d <%s>\n", nlh->
nlmsg_type, buf);
903 fprintf(ofd,
" .nlmsg_flags = %d <%s>\n", nlh->
nlmsg_flags,
904 nl_nlmsg_flags2str(nlh->
nlmsg_flags, buf,
sizeof(buf)));
905 fprintf(ofd,
" .nlmsg_seq = %d\n", nlh->
nlmsg_seq);
906 fprintf(ofd,
" .nlmsg_pid = %d\n", nlh->
nlmsg_pid);
910 static void dump_attrs(FILE *ofd,
struct nlattr *attrs,
int attrlen,
917 int padlen, alen =
nla_len(nla);
919 prefix_line(ofd, prefix);
920 fprintf(ofd,
" [ATTR %02d%s] %d octets\n",
nla_type(nla),
921 nla->nla_type & NLA_F_NESTED ?
" NESTED" :
"",
924 if (nla->nla_type & NLA_F_NESTED)
925 dump_attrs(ofd,
nla_data(nla), alen, prefix+1);
927 dump_hex(ofd,
nla_data(nla), alen, prefix);
931 prefix_line(ofd, prefix);
932 fprintf(ofd,
" [PADDING] %d octets\n",
940 prefix_line(ofd, prefix);
941 fprintf(ofd,
" [LEFTOVER] %d octets\n", rem);
955 "-------------------------- BEGIN NETLINK MESSAGE "
956 "---------------------------\n");
958 fprintf(ofd,
" [HEADER] %Zu octets\n",
sizeof(
struct nlmsghdr));
963 struct nl_msg *errmsg;
966 fprintf(ofd,
" [ERRORMSG] %Zu octets\n",
sizeof(*err));
967 fprintf(ofd,
" .error = %d \"%s\"\n", err->
error,
968 strerror(-err->
error));
969 fprintf(ofd,
" [ORIGINAL MESSAGE] %Zu octets\n",
sizeof(*hdr));
972 print_hdr(ofd, errmsg);
983 payloadlen -= attrlen;
986 fprintf(ofd,
" [PAYLOAD] %d octets\n", payloadlen);
987 dump_hex(ofd,
nlmsg_data(hdr), payloadlen, 0);
990 struct nlattr *attrs;
995 dump_attrs(ofd, attrs, attrlen, 0);
1000 "--------------------------- END NETLINK MESSAGE "
1001 "---------------------------\n");
int nla_validate(struct nlattr *head, int len, int maxtype, struct nla_policy *policy)
Validate a stream of attributes.
Message type to cache action association.
struct nl_msg * nlmsg_alloc_size(size_t max)
Allocate a new netlink message with maximum payload size specified.
int nla_padlen(int payload)
length of padding at the tail of the attribute
char * mt_name
Name of operation for human-readable printing.
int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
length of attributes data
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
uint16_t nlmsg_type
Message type (content type)
struct nl_msg * nlmsg_inherit(struct nlmsghdr *hdr)
Allocate a new netlink message and inherit netlink message header.
void * nlmsg_reserve(struct nl_msg *n, size_t len, int pad)
Reserve room for additional data in a netlink message.
attribute validation policy
struct nl_msg * nlmsg_alloc(void)
Allocate a new netlink message with the default maximum payload size.
uint32_t nlmsg_seq
Sequence number.
void nlmsg_set_default_size(size_t max)
Set the default maximum message payload size for allocated messages.
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
int error
Error code (errno number)
int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
check if the netlink message fits into the remaining bytes
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
#define NLMSG_OVERRUN
The message signals that data got lost.
uint32_t nlmsg_len
Length of message including header.
struct nlattr * nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype)
nlmsg_find_attr - find a specific attribute in a netlink message
#define NLMSG_ERROR
The message signals an error and the payload contains a nlmsgerr structure.
int nlmsg_total_size(int payload)
length of netlink message including padding
struct nlattr * nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen)
head of attributes data
struct nlmsghdr * nlmsg_next(struct nlmsghdr *nlh, int *remaining)
next netlink message in message stream
struct nlmsghdr * nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags)
Add a netlink message header to a netlink message.
uint32_t nlmsg_pid
Netlink PID of the proccess sending the message.
void nl_msg_dump(struct nl_msg *msg, FILE *ofd)
Dump message in human readable format to file descriptor.
int nla_type(const struct nlattr *nla)
attribute type
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
void * nla_data(const struct nlattr *nla)
head of payload
int nlmsg_expand(struct nl_msg *n, size_t newlen)
Expand maximum payload size of a netlink message.
int nla_len(const struct nlattr *nla)
length of payload
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, struct nla_policy *policy)
Parse a stream of attributes into a tb buffer.
int nlmsg_padlen(int payload)
length of padding at the message's tail
struct nlattr * nla_find(struct nlattr *head, int len, int attrtype)
Find a specific attribute in a stream of attributes.
uint16_t nlmsg_flags
Message flags.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
struct nlmsghdr msg
Original netlink message causing the error.
#define NLMSG_DONE
Message terminates a multipart message.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
int nlmsg_len(const struct nlmsghdr *nlh)
length of message payload
#define NLMSG_NOOP
No operation, message must be ignored.
struct nl_cache_ops * nl_cache_ops_associate(int protocol, int msgtype)
Associate a message type to a set of cache operations.
int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, struct nla_policy *policy)
nlmsg_validate - validate a netlink message including attributes
struct nl_msg * nlmsg_convert(struct nlmsghdr *hdr)
Convert a netlink message received from a netlink socket to a nl_msg.
int nlmsg_msg_size(int payload)
length of netlink message not including padding
struct nl_msgtype * nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)
Lookup message type cache association.
#define nla_for_each_attr(pos, head, len, rem)
iterate over a stream of attributes