/** * mnl_nlmsg_fprintf - print netlink message to file * \param fd pointer to file type * \param data pointer to the buffer that contains messages to be printed * \param datalen length of data stored in the buffer * \param extra_header_size size of the extra header (if any) * * This function prints the netlink header to a file handle. * It may be useful for debugging purposes. One example of the output * is the following: * *\verbatim ---------------- ------------------ | 0000000040 | | message length | | 00016 | R-A- | | type | flags | | 1289148991 | | sequence number| | 0000000000 | | port ID | ---------------- ------------------ | 00 00 00 00 | | extra header | | 00 00 00 00 | | extra header | | 01 00 00 00 | | extra header | | 01 00 00 00 | | extra header | |00008|--|00003| |len |flags| type| | 65 74 68 30 | | data | e t h 0 ---------------- ------------------ \endverbatim * * This example above shows the netlink message that is send to kernel-space * to set up the link interface eth0. The netlink and attribute header data * are displayed in base 10 whereas the extra header and the attribute payload * are expressed in base 16. The possible flags in the netlink header are: * * - R, that indicates that NLM_F_REQUEST is set. * - M, that indicates that NLM_F_MULTI is set. * - A, that indicates that NLM_F_ACK is set. * - E, that indicates that NLM_F_ECHO is set. * * The lack of one flag is displayed with '-'. On the other hand, the possible * attribute flags available are: * * - N, that indicates that NLA_F_NESTED is set. * - B, that indicates that NLA_F_NET_BYTEORDER is set. */ void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size) { const struct nlmsghdr *nlh = data; int len = datalen; while (mnl_nlmsg_ok(nlh, len)) { mnl_nlmsg_fprintf_header(fd, nlh); mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size); nlh = mnl_nlmsg_next(nlh, &len); } }
//libuv dgram socket callback. Only checks if message is of right type and then //call function for parsing message static void neat_linux_nl_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned int flags) { struct neat_ctx *nc = (struct neat_ctx*) handle->data; struct nlmsghdr *nl_hdr = (struct nlmsghdr*) buf->base; //We don't need any check here, we don't read more than 8192 bytes in one go int numbytes = (int) nread; while (mnl_nlmsg_ok(nl_hdr, numbytes)) { if (nl_hdr->nlmsg_type == RTM_NEWADDR || nl_hdr->nlmsg_type == RTM_DELADDR) neat_linux_handle_addr(nc, nl_hdr); nl_hdr = mnl_nlmsg_next(nl_hdr, &numbytes); } }
static inline int __mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, unsigned int portid, mnl_cb_t cb_data, void *data, mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len) { int ret = MNL_CB_OK, len = numbytes; const struct nlmsghdr *nlh = buf; while (mnl_nlmsg_ok(nlh, len)) { /* check message source */ if (!mnl_nlmsg_portid_ok(nlh, portid)) { errno = ESRCH; return -1; } /* perform sequence tracking */ if (!mnl_nlmsg_seq_ok(nlh, seq)) { errno = EPROTO; return -1; } /* netlink data message handling */ if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { if (cb_data){ ret = cb_data(nlh, data); if (ret <= MNL_CB_STOP) goto out; } } else if (nlh->nlmsg_type < cb_ctl_array_len) { if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) { ret = cb_ctl_array[nlh->nlmsg_type](nlh, data); if (ret <= MNL_CB_STOP) goto out; } } else if (default_cb_array[nlh->nlmsg_type]) { ret = default_cb_array[nlh->nlmsg_type](nlh, data); if (ret <= MNL_CB_STOP) goto out; } nlh = mnl_nlmsg_next(nlh, &len); } out: return ret; }