1 /* 2 * Copyright (c) 2026 Ishan Agrawal 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <sys/param.h> 8 #include <netlink/netlink.h> 9 10 #include <stdio.h> 11 #include <stdbool.h> 12 #include <stddef.h> 13 14 #include "sysdecode.h" 15 16 /* 17 * Decodes a buffer as a Netlink message stream. 18 * 19 * Returns true if the data was successfully decoded as Netlink. 20 * Returns false if the data is malformed, allowing the caller 21 * to fallback to a standard hex/string dump. 22 */ 23 bool 24 sysdecode_netlink(FILE *fp, const void *buf, size_t len) 25 { 26 const struct nlmsghdr *nl = buf; 27 size_t remaining = len; 28 bool first = true; 29 30 /* Basic sanity check: Buffer must be at least one header size. */ 31 if (remaining < sizeof(struct nlmsghdr)) 32 return (false); 33 34 /* * Protocol Sanity Check: 35 * The first message length must be valid (>= header) and fit 36 * inside the provided buffer snapshot. 37 */ 38 if (nl->nlmsg_len < sizeof(struct nlmsghdr) || nl->nlmsg_len > remaining) 39 return (false); 40 41 fprintf(fp, "netlink{"); 42 43 while (remaining >= sizeof(struct nlmsghdr)) { 44 if (!first) 45 fprintf(fp, ","); 46 47 /* Safety check for current message. */ 48 if (nl->nlmsg_len < sizeof(struct nlmsghdr) || 49 nl->nlmsg_len > remaining) { 50 fprintf(fp, "<truncated>"); 51 break; 52 } 53 54 fprintf(fp, "len=%u,type=", nl->nlmsg_len); 55 56 /* Decode Standard Message Types. */ 57 switch (nl->nlmsg_type) { 58 case NLMSG_NOOP: 59 fprintf(fp, "NLMSG_NOOP"); 60 break; 61 case NLMSG_ERROR: 62 fprintf(fp, "NLMSG_ERROR"); 63 break; 64 case NLMSG_DONE: 65 fprintf(fp, "NLMSG_DONE"); 66 break; 67 case NLMSG_OVERRUN: 68 fprintf(fp, "NLMSG_OVERRUN"); 69 break; 70 default: 71 fprintf(fp, "%u", nl->nlmsg_type); 72 break; 73 } 74 75 fprintf(fp, ",flags="); 76 /* TODO: decode flags symbolically using sysdecode_mask. */ 77 fprintf(fp, "0x%x", nl->nlmsg_flags); 78 79 fprintf(fp, ",seq=%u,pid=%u", nl->nlmsg_seq, nl->nlmsg_pid); 80 81 /* Handle Alignment (Netlink messages are 4-byte aligned). */ 82 size_t aligned_len = NLMSG_ALIGN(nl->nlmsg_len); 83 if (aligned_len > remaining) 84 remaining = 0; 85 else 86 remaining -= aligned_len; 87 88 nl = (const struct nlmsghdr *)(const void *)((const char *)nl + aligned_len); 89 first = false; 90 } 91 92 fprintf(fp, "}"); 93 return (true); 94 } 95