/* * Copyright (c) 2026 Ishan Agrawal * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include "sysdecode.h" /* * Decodes a buffer as a Netlink message stream. * * Returns true if the data was successfully decoded as Netlink. * Returns false if the data is malformed, allowing the caller * to fallback to a standard hex/string dump. */ bool sysdecode_netlink(FILE *fp, const void *buf, size_t len) { const struct nlmsghdr *nl = buf; size_t remaining = len; bool first = true; /* Basic sanity check: Buffer must be at least one header size. */ if (remaining < sizeof(struct nlmsghdr)) return (false); /* * Protocol Sanity Check: * The first message length must be valid (>= header) and fit * inside the provided buffer snapshot. */ if (nl->nlmsg_len < sizeof(struct nlmsghdr) || nl->nlmsg_len > remaining) return (false); fprintf(fp, "netlink{"); while (remaining >= sizeof(struct nlmsghdr)) { if (!first) fprintf(fp, ","); /* Safety check for current message. */ if (nl->nlmsg_len < sizeof(struct nlmsghdr) || nl->nlmsg_len > remaining) { fprintf(fp, ""); break; } fprintf(fp, "len=%u,type=", nl->nlmsg_len); /* Decode Standard Message Types. */ switch (nl->nlmsg_type) { case NLMSG_NOOP: fprintf(fp, "NLMSG_NOOP"); break; case NLMSG_ERROR: fprintf(fp, "NLMSG_ERROR"); break; case NLMSG_DONE: fprintf(fp, "NLMSG_DONE"); break; case NLMSG_OVERRUN: fprintf(fp, "NLMSG_OVERRUN"); break; default: fprintf(fp, "%u", nl->nlmsg_type); break; } fprintf(fp, ",flags="); /* TODO: decode flags symbolically using sysdecode_mask. */ fprintf(fp, "0x%x", nl->nlmsg_flags); fprintf(fp, ",seq=%u,pid=%u", nl->nlmsg_seq, nl->nlmsg_pid); /* Handle Alignment (Netlink messages are 4-byte aligned). */ size_t aligned_len = NLMSG_ALIGN(nl->nlmsg_len); if (aligned_len > remaining) remaining = 0; else remaining -= aligned_len; nl = (const struct nlmsghdr *)(const void *)((const char *)nl + aligned_len); first = false; } fprintf(fp, "}"); return (true); }