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 >= (
int)
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 tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
520 if ((tlen + nlmsg_len) > n->nm_size) {
526 n->nm_nlh->nlmsg_len += tlen;
529 memset(buf + len, 0, tlen - len);
531 NL_DBG(2,
"msg %p: Reserved %zu bytes, pad=%d, nlmsg_len=%d\n",
532 n, len, pad, n->nm_nlh->nlmsg_len);
555 return nl_errno(ENOMEM);
557 memcpy(tmp, data, len);
558 NL_DBG(2,
"msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
581 if (newlen <= n->nm_size)
582 return nl_errno(EINVAL);
584 tmp = realloc(n->nm_nlh, newlen);
586 return nl_errno(ENOMEM);
611 int type,
int payload,
int flags)
615 if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
618 nlh = (
struct nlmsghdr *) n->nm_nlh;
624 NL_DBG(2,
"msg %p: Added netlink header type=%d, flags=%d, pid=%d, "
625 "seq=%d\n", n, type, flags, pid, seq);
663 NL_DBG(2,
"msg %p: Freed\n", n);
673 void nlmsg_set_proto(
struct nl_msg *msg,
int protocol)
675 msg->nm_protocol = protocol;
678 int nlmsg_get_proto(
struct nl_msg *msg)
680 return msg->nm_protocol;
683 size_t nlmsg_get_max_size(
struct nl_msg *msg)
688 void nlmsg_set_src(
struct nl_msg *msg,
struct sockaddr_nl *addr)
690 memcpy(&msg->nm_src, addr,
sizeof(*addr));
693 struct sockaddr_nl *nlmsg_get_src(
struct nl_msg *msg)
698 void nlmsg_set_dst(
struct nl_msg *msg,
struct sockaddr_nl *addr)
700 memcpy(&msg->nm_dst, addr,
sizeof(*addr));
703 struct sockaddr_nl *nlmsg_get_dst(
struct nl_msg *msg)
708 void nlmsg_set_creds(
struct nl_msg *msg,
struct ucred *creds)
710 memcpy(&msg->nm_creds, creds,
sizeof(*creds));
711 msg->nm_flags |= NL_MSG_CRED_PRESENT;
714 struct ucred *nlmsg_get_creds(
struct nl_msg *msg)
716 if (msg->nm_flags & NL_MSG_CRED_PRESENT)
717 return &msg->nm_creds;
728 static struct trans_tbl nl_msgtypes[] = {
735 char *nl_nlmsgtype2str(
int type,
char *buf,
size_t size)
737 return __type2str(type, buf, size, nl_msgtypes,
738 ARRAY_SIZE(nl_msgtypes));
741 int nl_str2nlmsgtype(
const char *name)
743 return __str2type(name, nl_msgtypes, ARRAY_SIZE(nl_msgtypes));
753 char *nl_nlmsg_flags2str(
int flags,
char *buf,
size_t len)
757 #define PRINT_FLAG(f) \
758 if (flags & NLM_F_##f) { \
759 flags &= ~NLM_F_##f; \
760 strncat(buf, #f, len - strlen(buf) - 1); \
762 strncat(buf, ",", len - strlen(buf) - 1); \
779 snprintf(s,
sizeof(s),
"0x%x", flags);
780 strncat(buf, s, len - strlen(buf) - 1);
796 void (*cb)(
struct nl_object *,
void *);
803 struct dp_xdata *x = p->pp_arg;
809 int nl_msg_parse(
struct nl_msg *msg,
void (*cb)(
struct nl_object *,
void *),
816 struct dp_xdata x = {
824 return nl_error(ENOENT,
"Unknown message type %d",
828 return nl_cache_parse(ops, NULL,
nlmsg_hdr(msg), &p);
838 static void prefix_line(FILE *ofd,
int prefix)
842 for (i = 0; i < prefix; i++)
846 static inline void dump_hex(FILE *ofd,
char *start,
int len,
int prefix)
849 char ascii[21] = {0};
851 limit = 18 - (prefix * 2);
852 prefix_line(ofd, prefix);
855 for (i = 0, a = 0, c = 0; i < len; i++) {
856 int v = *(uint8_t *) (start + i);
858 fprintf(ofd,
"%02x ", v);
859 ascii[a++] = isprint(v) ? v :
'.';
862 fprintf(ofd,
"%s\n", ascii);
864 prefix_line(ofd, prefix);
868 memset(ascii, 0,
sizeof(ascii));
874 for (i = 0; i < (limit - c); i++)
876 fprintf(ofd,
"%s\n", ascii);
880 static void print_hdr(FILE *ofd,
struct nl_msg *msg)
887 fprintf(ofd,
" .nlmsg_len = %d\n", nlh->
nlmsg_len);
895 snprintf(buf,
sizeof(buf),
"%s::%s", ops->co_name, mt->
mt_name);
897 nl_nlmsgtype2str(nlh->
nlmsg_type, buf,
sizeof(buf));
899 fprintf(ofd,
" .nlmsg_type = %d <%s>\n", nlh->
nlmsg_type, buf);
900 fprintf(ofd,
" .nlmsg_flags = %d <%s>\n", nlh->
nlmsg_flags,
901 nl_nlmsg_flags2str(nlh->
nlmsg_flags, buf,
sizeof(buf)));
902 fprintf(ofd,
" .nlmsg_seq = %d\n", nlh->
nlmsg_seq);
903 fprintf(ofd,
" .nlmsg_pid = %d\n", nlh->
nlmsg_pid);
907 static void dump_attrs(FILE *ofd,
struct nlattr *attrs,
int attrlen,
914 int padlen, alen =
nla_len(nla);
916 prefix_line(ofd, prefix);
917 fprintf(ofd,
" [ATTR %02d%s] %d octets\n",
nla_type(nla),
918 nla->nla_type & NLA_F_NESTED ?
" NESTED" :
"",
921 if (nla->nla_type & NLA_F_NESTED)
922 dump_attrs(ofd,
nla_data(nla), alen, prefix+1);
924 dump_hex(ofd,
nla_data(nla), alen, prefix);
928 prefix_line(ofd, prefix);
929 fprintf(ofd,
" [PADDING] %d octets\n",
937 prefix_line(ofd, prefix);
938 fprintf(ofd,
" [LEFTOVER] %d octets\n", rem);
952 "-------------------------- BEGIN NETLINK MESSAGE "
953 "---------------------------\n");
955 fprintf(ofd,
" [HEADER] %Zu octets\n",
sizeof(
struct nlmsghdr));
960 struct nl_msg *errmsg;
964 fprintf(ofd,
" [ERRORMSG] %Zu octets\n",
sizeof(*err));
965 fprintf(ofd,
" .error = %d \"%s\"\n", err->
error,
966 strerror_r(-err->
error, buf,
sizeof(buf)));
967 fprintf(ofd,
" [ORIGINAL MESSAGE] %Zu octets\n",
sizeof(*hdr));
970 print_hdr(ofd, errmsg);
981 payloadlen -= attrlen;
984 fprintf(ofd,
" [PAYLOAD] %d octets\n", payloadlen);
985 dump_hex(ofd,
nlmsg_data(hdr), payloadlen, 0);
988 struct nlattr *attrs;
993 dump_attrs(ofd, attrs, attrlen, 0);
998 "--------------------------- END NETLINK MESSAGE "
999 "---------------------------\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 protocol and message type to 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