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");