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();
188 return NLMSG_HDRLEN + payload;
191 static int nlmsg_msg_size(
int payload)
206 return NLMSG_ALIGN(nlmsg_msg_size(payload));
239 return (
unsigned char *) nlh + NLMSG_HDRLEN;
242 void *nlmsg_tail(
const struct nlmsghdr *nlh)
244 return (
unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len);
255 return nlh->nlmsg_len - NLMSG_HDRLEN;
258 static int nlmsg_len(
const struct nlmsghdr *nlh)
278 return (
struct nlattr *) (data + NLMSG_ALIGN(hdrlen));
288 return nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen);
298 int nlmsg_valid_hdr(
const struct nlmsghdr *nlh,
int hdrlen)
300 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
311 int nlmsg_ok(
const struct nlmsghdr *nlh,
int remaining)
313 return (remaining >= (
int)
sizeof(
struct nlmsghdr) &&
314 nlh->nlmsg_len >=
sizeof(
struct nlmsghdr) &&
315 nlh->nlmsg_len <= remaining);
326 struct nlmsghdr *
nlmsg_next(
struct nlmsghdr *nlh,
int *remaining)
328 int totlen = NLMSG_ALIGN(nlh->nlmsg_len);
330 *remaining -= totlen;
332 return (
struct nlmsghdr *) ((
unsigned char *) nlh + totlen);
345 int nlmsg_parse(
struct nlmsghdr *nlh,
int hdrlen,
struct nlattr *tb[],
348 if (!nlmsg_valid_hdr(nlh, hdrlen))
349 return -NLE_MSG_TOOSHORT;
379 if (!nlmsg_valid_hdr(nlh, hdrlen))
380 return -NLE_MSG_TOOSHORT;
393 static struct nl_msg *__nlmsg_alloc(
size_t len)
397 if (len <
sizeof(
struct nlmsghdr))
398 len =
sizeof(
struct nlmsghdr);
400 nm = calloc(1,
sizeof(*nm));
406 nm->nm_nlh = calloc(1, len);
410 memset(nm->nm_nlh, 0,
sizeof(
struct nlmsghdr));
412 nm->nm_protocol = -1;
416 NL_DBG(2,
"msg %p: Allocated new message, maxlen=%zu\n", nm, len);
435 return __nlmsg_alloc(default_msg_size);
443 return __nlmsg_alloc(max);
462 struct nlmsghdr *
new = nm->nm_nlh;
464 new->nlmsg_type = hdr->nlmsg_type;
465 new->nlmsg_flags = hdr->nlmsg_flags;
466 new->nlmsg_seq = hdr->nlmsg_seq;
467 new->nlmsg_pid = hdr->nlmsg_pid;
483 struct nlmsghdr nlh = {
484 .nlmsg_type = nlmsgtype,
485 .nlmsg_flags = flags,
490 NL_DBG(2,
"msg %p: Allocated new simple message\n", msg);
504 default_msg_size = max;
520 nm = __nlmsg_alloc(NLMSG_ALIGN(hdr->nlmsg_len));
524 memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len);
546 void *buf = n->nm_nlh;
547 size_t nlmsg_len = n->nm_nlh->nlmsg_len;
550 if (len > n->nm_size)
553 tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len;
555 if ((tlen + nlmsg_len) > n->nm_size)
559 n->nm_nlh->nlmsg_len += tlen;
562 memset(buf + len, 0, tlen - len);
564 NL_DBG(2,
"msg %p: Reserved %zu (%zu) bytes, pad=%d, nlmsg_len=%d\n",
565 n, tlen, len, pad, n->nm_nlh->nlmsg_len);
590 memcpy(tmp, data, len);
591 NL_DBG(2,
"msg %p: Appended %zu bytes with padding %d\n", n, len, pad);
614 if (newlen <= n->nm_size)
617 tmp = realloc(n->nm_nlh, newlen);
643 struct nlmsghdr *
nlmsg_put(
struct nl_msg *n, uint32_t pid, uint32_t seq,
644 int type,
int payload,
int flags)
646 struct nlmsghdr *nlh;
648 if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN)
651 nlh = (
struct nlmsghdr *) n->nm_nlh;
652 nlh->nlmsg_type = type;
653 nlh->nlmsg_flags = flags;
654 nlh->nlmsg_pid = pid;
655 nlh->nlmsg_seq = seq;
657 NL_DBG(2,
"msg %p: Added netlink header type=%d, flags=%d, pid=%d, "
658 "seq=%d\n", n, type, flags, pid, seq);
688 NL_DBG(4,
"New reference to message %p, total %d\n",
689 msg, msg->nm_refcnt);
704 NL_DBG(4,
"Returned message reference %p, %d remaining\n",
705 msg, msg->nm_refcnt);
707 if (msg->nm_refcnt < 0)
710 if (msg->nm_refcnt <= 0) {
713 NL_DBG(2,
"msg %p: Freed\n", msg);
724 void nlmsg_set_proto(
struct nl_msg *msg,
int protocol)
726 msg->nm_protocol = protocol;
729 int nlmsg_get_proto(
struct nl_msg *msg)
731 return msg->nm_protocol;
734 size_t nlmsg_get_max_size(
struct nl_msg *msg)
739 void nlmsg_set_src(
struct nl_msg *msg,
struct sockaddr_nl *addr)
741 memcpy(&msg->nm_src, addr,
sizeof(*addr));
744 struct sockaddr_nl *nlmsg_get_src(
struct nl_msg *msg)
749 void nlmsg_set_dst(
struct nl_msg *msg,
struct sockaddr_nl *addr)
751 memcpy(&msg->nm_dst, addr,
sizeof(*addr));
754 struct sockaddr_nl *nlmsg_get_dst(
struct nl_msg *msg)
759 void nlmsg_set_creds(
struct nl_msg *msg,
struct ucred *creds)
761 memcpy(&msg->nm_creds, creds,
sizeof(*creds));
762 msg->nm_flags |= NL_MSG_CRED_PRESENT;
765 struct ucred *nlmsg_get_creds(
struct nl_msg *msg)
767 if (msg->nm_flags & NL_MSG_CRED_PRESENT)
768 return &msg->nm_creds;
779 static const struct trans_tbl nl_msgtypes[] = {
780 __ADD(NLMSG_NOOP,NOOP)
781 __ADD(NLMSG_ERROR,ERROR)
782 __ADD(NLMSG_DONE,DONE)
783 __ADD(NLMSG_OVERRUN,OVERRUN)
786 char *nl_nlmsgtype2str(
int type,
char *buf,
size_t size)
788 return __type2str(type, buf, size, nl_msgtypes,
789 ARRAY_SIZE(nl_msgtypes));
792 int nl_str2nlmsgtype(
const char *name)
794 return __str2type(name, nl_msgtypes, ARRAY_SIZE(nl_msgtypes));
804 char *nl_nlmsg_flags2str(
int flags,
char *buf,
size_t len)
808 #define PRINT_FLAG(f) \
809 if (flags & NLM_F_##f) { \
810 flags &= ~NLM_F_##f; \
811 strncat(buf, #f, len - strlen(buf) - 1); \
813 strncat(buf, ",", len - strlen(buf) - 1); \
830 snprintf(s,
sizeof(s),
"0x%x", flags);
831 strncat(buf, s, len - strlen(buf) - 1);
854 struct dp_xdata *x = p->
pp_arg;
860 int nl_msg_parse(
struct nl_msg *msg,
void (*cb)(
struct nl_object *,
void *),
867 struct dp_xdata x = {
875 return -NLE_MSGTYPE_NOSUPPORT;
878 return nl_cache_parse(ops, NULL,
nlmsg_hdr(msg), &p);
888 static void prefix_line(FILE *ofd,
int prefix)
892 for (i = 0; i < prefix; i++)
896 static inline void dump_hex(FILE *ofd,
char *start,
int len,
int prefix)
899 char ascii[21] = {0};
901 limit = 18 - (prefix * 2);
902 prefix_line(ofd, prefix);
905 for (i = 0, a = 0, c = 0; i < len; i++) {
906 int v = *(uint8_t *) (start + i);
908 fprintf(ofd,
"%02x ", v);
909 ascii[a++] = isprint(v) ? v :
'.';
912 fprintf(ofd,
"%s\n", ascii);
914 prefix_line(ofd, prefix);
918 memset(ascii, 0,
sizeof(ascii));
924 for (i = 0; i < (limit - c); i++)
926 fprintf(ofd,
"%s\n", ascii);
930 static void print_hdr(FILE *ofd,
struct nl_msg *msg)
937 fprintf(ofd,
" .nlmsg_len = %d\n", nlh->nlmsg_len);
947 nl_nlmsgtype2str(nlh->nlmsg_type, buf,
sizeof(buf));
949 fprintf(ofd,
" .nlmsg_type = %d <%s>\n", nlh->nlmsg_type, buf);
950 fprintf(ofd,
" .nlmsg_flags = %d <%s>\n", nlh->nlmsg_flags,
951 nl_nlmsg_flags2str(nlh->nlmsg_flags, buf,
sizeof(buf)));
952 fprintf(ofd,
" .nlmsg_seq = %d\n", nlh->nlmsg_seq);
953 fprintf(ofd,
" .nlmsg_pid = %d\n", nlh->nlmsg_pid);
957 static void dump_attrs(FILE *ofd,
struct nlattr *attrs,
int attrlen,
964 int padlen, alen =
nla_len(nla);
966 prefix_line(ofd, prefix);
967 fprintf(ofd,
" [ATTR %02d%s] %d octets\n",
nla_type(nla),
968 nla->nla_type & NLA_F_NESTED ?
" NESTED" :
"",
971 if (nla->nla_type & NLA_F_NESTED)
972 dump_attrs(ofd,
nla_data(nla), alen, prefix+1);
974 dump_hex(ofd,
nla_data(nla), alen, prefix);
978 prefix_line(ofd, prefix);
979 fprintf(ofd,
" [PADDING] %d octets\n",
987 prefix_line(ofd, prefix);
988 fprintf(ofd,
" [LEFTOVER] %d octets\n", rem);
1002 "-------------------------- BEGIN NETLINK MESSAGE "
1003 "---------------------------\n");
1005 fprintf(ofd,
" [HEADER] %Zu octets\n",
sizeof(
struct nlmsghdr));
1006 print_hdr(ofd, msg);
1008 if (hdr->nlmsg_type == NLMSG_ERROR &&
1009 hdr->nlmsg_len >= nlmsg_msg_size(
sizeof(
struct nlmsgerr))) {
1010 struct nl_msg *errmsg;
1013 fprintf(ofd,
" [ERRORMSG] %Zu octets\n",
sizeof(*err));
1014 fprintf(ofd,
" .error = %d \"%s\"\n", err->error,
1015 strerror(-err->error));
1016 fprintf(ofd,
" [ORIGINAL MESSAGE] %Zu octets\n",
sizeof(*hdr));
1019 print_hdr(ofd, errmsg);
1021 }
else if (nlmsg_len(hdr) > 0) {
1023 int payloadlen = nlmsg_len(hdr);
1030 payloadlen -= attrlen;
1033 fprintf(ofd,
" [PAYLOAD] %d octets\n", payloadlen);
1034 dump_hex(ofd,
nlmsg_data(hdr), payloadlen, 0);
1037 struct nlattr *attrs;
1042 dump_attrs(ofd, attrs, attrlen, 0);
1047 "--------------------------- END NETLINK MESSAGE "
1048 "---------------------------\n");