29 #include <netlink-private/netlink.h>
30 #include <netlink/netlink.h>
31 #include <netlink/utils.h>
32 #include <netlink/cache.h>
33 #include <netlink/attr.h>
34 #include <linux/socket.h>
36 static size_t default_msg_size;
38 static void __init init_msg_size(
void)
40 default_msg_size = getpagesize();
56 return NLMSG_HDRLEN + payload;
59 static int nlmsg_msg_size(
int payload)
74 return NLMSG_ALIGN(nlmsg_msg_size(payload));
107 return (
unsigned char *) nlh + NLMSG_HDRLEN;
110 void *nlmsg_tail(
const struct nlmsghdr *nlh)
112 return (
unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
123 return nlh->nlmsg_len - NLMSG_HDRLEN;
126 static int nlmsg_len(
const struct nlmsghdr *nlh)
146 return (
struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
156 return max_t(
int, nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen), 0);
166 int nlmsg_valid_hdr(
const struct nlmsghdr *nlh,
int hdrlen)
168 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
179 int nlmsg_ok(
const struct nlmsghdr *nlh,
int remaining)
181 return (remaining >= (
int)
sizeof(
struct nlmsghdr) &&
182 nlh->nlmsg_len >=
sizeof(
struct nlmsghdr) &&
183 nlh->nlmsg_len <= remaining);
194 struct nlmsghdr *
nlmsg_next(
struct nlmsghdr *nlh,
int *remaining)
196 int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
198 *remaining -= totlen;
200 return (
struct nlmsghdr *) ((
unsigned char *) nlh + totlen);
213 int nlmsg_parse(
struct nlmsghdr *nlh,
int hdrlen,
struct nlattr *tb[],
216 if (!nlmsg_valid_hdr(nlh, hdrlen))
217 return -NLE_MSG_TOOSHORT;
247 if (!nlmsg_valid_hdr(nlh, hdrlen))
248 return -NLE_MSG_TOOSHORT;
261 static struct nl_msg *__nlmsg_alloc(
size_t len)
265 if (len <
sizeof(
struct nlmsghdr))
266 len =
sizeof(
struct nlmsghdr);
268 nm = calloc(1,
sizeof(*nm));
274 nm->nm_nlh = calloc(1, len);
278 nm->nm_protocol = -1;
282 NL_DBG(2,
"msg %p: Allocated new message, maxlen=%zu\n", nm, len);
301 return __nlmsg_alloc(default_msg_size);
309 return __nlmsg_alloc(max);
328 struct nlmsghdr *
new = nm->nm_nlh;
330 new->nlmsg_type = hdr->nlmsg_type;
331 new->nlmsg_flags = hdr->nlmsg_flags;
332 new->nlmsg_seq = hdr->nlmsg_seq;
333 new->nlmsg_pid = hdr->nlmsg_pid;
349 struct nlmsghdr nlh = {
350 .nlmsg_type = nlmsgtype,
351 .nlmsg_flags = flags,
356 NL_DBG(2,
"msg %p: Allocated new simple message\n", msg);
370 default_msg_size = max;
386 nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len));
390 memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len);
412 void *buf = n->nm_nlh;
413 size_t nlmsg_len = n->nm_nlh->nlmsg_len;
416 tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
418 if ((tlen + nlmsg_len) > n->nm_size)
422 n->nm_nlh->nlmsg_len += tlen;
425 memset(buf + len, 0, tlen - len);
427 NL_DBG(2,
"msg %p: Reserved %zu (%zu) bytes, pad=%d, nlmsg_len=%d\n",
428 n, tlen, len, pad, n->nm_nlh->nlmsg_len);
453 memcpy(tmp, data, len);
454 NL_DBG(2,
"msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
477 if (newlen <= n->nm_size)
480 tmp = realloc(n->nm_nlh, newlen);
506 struct nlmsghdr *
nlmsg_put(
struct nl_msg *n, uint32_t pid, uint32_t seq,
507 int type,
int payload,
int flags)
509 struct nlmsghdr *nlh;
511 if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
514 nlh = (
struct nlmsghdr *) n->nm_nlh;
515 nlh->nlmsg_type = type;
516 nlh->nlmsg_flags = flags;
517 nlh->nlmsg_pid = pid;
518 nlh->nlmsg_seq = seq;
520 NL_DBG(2,
"msg %p: Added netlink header type=%d, flags=%d, pid=%d, "
521 "seq=%d\n", n, type, flags, pid, seq);
551 NL_DBG(4,
"New reference to message %p, total %d\n",
552 msg, msg->nm_refcnt);
567 NL_DBG(4,
"Returned message reference %p, %d remaining\n",
568 msg, msg->nm_refcnt);
570 if (msg->nm_refcnt < 0)
573 if (msg->nm_refcnt <= 0) {
576 NL_DBG(2,
"msg %p: Freed\n", msg);
587 void nlmsg_set_proto(
struct nl_msg *msg,
int protocol)
589 msg->nm_protocol = protocol;
592 int nlmsg_get_proto(
struct nl_msg *msg)
594 return msg->nm_protocol;
597 size_t nlmsg_get_max_size(
struct nl_msg *msg)
602 void nlmsg_set_src(
struct nl_msg *msg,
struct sockaddr_nl *addr)
604 memcpy(&msg->nm_src, addr,
sizeof(*addr));
607 struct sockaddr_nl *nlmsg_get_src(
struct nl_msg *msg)
612 void nlmsg_set_dst(
struct nl_msg *msg,
struct sockaddr_nl *addr)
614 memcpy(&msg->nm_dst, addr,
sizeof(*addr));
617 struct sockaddr_nl *nlmsg_get_dst(
struct nl_msg *msg)
622 void nlmsg_set_creds(
struct nl_msg *msg,
struct ucred *creds)
624 memcpy(&msg->nm_creds, creds,
sizeof(*creds));
625 msg->nm_flags |= NL_MSG_CRED_PRESENT;
628 struct ucred *nlmsg_get_creds(
struct nl_msg *msg)
630 if (msg->nm_flags & NL_MSG_CRED_PRESENT)
631 return &msg->nm_creds;
642 static const struct trans_tbl nl_msgtypes[] = {
643 __ADD(NLMSG_NOOP,NOOP)
644 __ADD(NLMSG_ERROR,ERROR)
645 __ADD(NLMSG_DONE,DONE)
646 __ADD(NLMSG_OVERRUN,OVERRUN)
649 char *nl_nlmsgtype2str(
int type,
char *buf,
size_t size)
651 return __type2str(type, buf, size, nl_msgtypes,
652 ARRAY_SIZE(nl_msgtypes));
655 int nl_str2nlmsgtype(
const char *name)
657 return __str2type(name, nl_msgtypes, ARRAY_SIZE(nl_msgtypes));
667 char *nl_nlmsg_flags2str(
int flags,
char *buf,
size_t len)
671 #define PRINT_FLAG(f) \
672 if (flags & NLM_F_##f) { \
673 flags &= ~NLM_F_##f; \
674 strncat(buf, #f, len - strlen(buf) - 1); \
676 strncat(buf, ",", len - strlen(buf) - 1); \
693 snprintf(s,
sizeof(s),
"0x%x", flags);
694 strncat(buf, s, len - strlen(buf) - 1);
710 void (*cb)(
struct nl_object *,
void *);
715 static int parse_cb(
struct nl_object *obj,
struct nl_parser_param *p)
717 struct dp_xdata *x = p->pp_arg;
723 int nl_msg_parse(
struct nl_msg *msg,
void (*cb)(
struct nl_object *,
void *),
726 struct nl_cache_ops *ops;
727 struct nl_parser_param p = {
730 struct dp_xdata x = {
739 return -NLE_MSGTYPE_NOSUPPORT;
742 err = nl_cache_parse(ops, NULL,
nlmsg_hdr(msg), &p);
755 static void prefix_line(FILE *ofd,
int prefix)
759 for (i = 0; i < prefix; i++)
763 static inline void dump_hex(FILE *ofd,
char *start,
int len,
int prefix)
766 char ascii[21] = {0};
768 limit = 16 - (prefix * 2);
769 prefix_line(ofd, prefix);
772 for (i = 0, a = 0, c = 0; i < len; i++) {
773 int v = *(uint8_t *) (start + i);
775 fprintf(ofd,
"%02x ", v);
776 ascii[a++] = isprint(v) ? v :
'.';
779 fprintf(ofd,
"%s\n", ascii);
781 prefix_line(ofd, prefix);
785 memset(ascii, 0,
sizeof(ascii));
790 for (i = 0; i < (limit - c); i++)
792 fprintf(ofd,
"%s\n", ascii);
796 static void print_hdr(FILE *ofd,
struct nl_msg *msg)
799 struct nl_cache_ops *ops;
800 struct nl_msgtype *mt;
803 fprintf(ofd,
" .nlmsg_len = %d\n", nlh->nlmsg_len);
811 snprintf(buf,
sizeof(buf),
"%s::%s", ops->co_name, mt->mt_name);
814 nl_nlmsgtype2str(nlh->nlmsg_type, buf,
sizeof(buf));
816 fprintf(ofd,
" .type = %d <%s>\n", nlh->nlmsg_type, buf);
817 fprintf(ofd,
" .flags = %d <%s>\n", nlh->nlmsg_flags,
818 nl_nlmsg_flags2str(nlh->nlmsg_flags, buf,
sizeof(buf)));
819 fprintf(ofd,
" .seq = %d\n", nlh->nlmsg_seq);
820 fprintf(ofd,
" .port = %d\n", nlh->nlmsg_pid);
824 static void print_genl_hdr(FILE *ofd,
void *start)
826 struct genlmsghdr *ghdr = start;
828 fprintf(ofd,
" [GENERIC NETLINK HEADER] %zu octets\n", GENL_HDRLEN);
829 fprintf(ofd,
" .cmd = %u\n", ghdr->cmd);
830 fprintf(ofd,
" .version = %u\n", ghdr->version);
831 fprintf(ofd,
" .unused = %#x\n", ghdr->reserved);
834 static void *print_genl_msg(
struct nl_msg *msg, FILE *ofd,
struct nlmsghdr *hdr,
835 struct nl_cache_ops *ops,
int *payloadlen)
839 if (*payloadlen < GENL_HDRLEN)
842 print_genl_hdr(ofd, data);
844 *payloadlen -= GENL_HDRLEN;
848 int hdrsize = ops->co_hdrsize - GENL_HDRLEN;
851 if (*payloadlen < hdrsize)
854 fprintf(ofd,
" [HEADER] %d octets\n", hdrsize);
855 dump_hex(ofd, data, hdrsize, 0);
857 *payloadlen -= hdrsize;
865 static void dump_attr(FILE *ofd,
struct nlattr *attr,
int prefix)
869 dump_hex(ofd,
nla_data(attr), len, prefix);
872 static void dump_attrs(FILE *ofd,
struct nlattr *attrs,
int attrlen,
879 int padlen, alen =
nla_len(nla);
881 prefix_line(ofd, prefix);
883 if (nla->nla_type == 0)
884 fprintf(ofd,
" [ATTR PADDING] %d octets\n", alen);
886 fprintf(ofd,
" [ATTR %02d%s] %d octets\n",
nla_type(nla),
891 dump_attrs(ofd,
nla_data(nla), alen, prefix+1);
893 dump_attr(ofd, nla, prefix);
897 prefix_line(ofd, prefix);
898 fprintf(ofd,
" [PADDING] %d octets\n",
906 prefix_line(ofd, prefix);
907 fprintf(ofd,
" [LEFTOVER] %d octets\n", rem);
911 static void dump_error_msg(
struct nl_msg *msg, FILE *ofd)
916 fprintf(ofd,
" [ERRORMSG] %zu octets\n",
sizeof(*err));
918 if (nlmsg_len(hdr) >=
sizeof(*err)) {
920 struct nl_msg *errmsg;
922 fprintf(ofd,
" .error = %d \"%s\"\n", err->error,
923 strerror_r(-err->error, buf,
sizeof(buf)));
924 fprintf(ofd,
" [ORIGINAL MESSAGE] %zu octets\n",
sizeof(*hdr));
927 print_hdr(ofd, errmsg);
932 static void print_msg(
struct nl_msg *msg, FILE *ofd,
struct nlmsghdr *hdr)
934 struct nl_cache_ops *ops;
935 int payloadlen = nlmsg_len(hdr);
944 payloadlen -= attrlen;
947 if (msg->nm_protocol == NETLINK_GENERIC)
948 data = print_genl_msg(msg, ofd, hdr, ops, &payloadlen);
951 fprintf(ofd,
" [PAYLOAD] %d octets\n", payloadlen);
952 dump_hex(ofd, data, payloadlen, 0);
956 struct nlattr *attrs;
961 dump_attrs(ofd, attrs, attrlen, 0);
978 "-------------------------- BEGIN NETLINK MESSAGE ---------------------------\n");
980 fprintf(ofd,
" [NETLINK HEADER] %zu octets\n",
sizeof(
struct nlmsghdr));
983 if (hdr->nlmsg_type == NLMSG_ERROR)
984 dump_error_msg(msg, ofd);
985 else if (nlmsg_len(hdr) > 0)
986 print_msg(msg, ofd, hdr);
989 "--------------------------- END NETLINK MESSAGE ---------------------------\n");