/** * mnl_nlmsg_put_extra_header - reserve and prepare room for an extra header * \param nlh pointer to Netlink header * \param size size of the extra header that we want to put * * This function sets to zero the room that is required to put the extra * header after the initial Netlink header. This function also increases * the nlmsg_len field. You have to invoke mnl_nlmsg_put_header() before * you call this function. This function returns a pointer to the extra * header. */ void * mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size) { char *ptr = (char *)nlh + nlh->nlmsg_len; nlh->nlmsg_len += MNL_ALIGN(size); memset(ptr, 0, size); return ptr; }
/** * mnl_attr_put_check - add an attribute to netlink message * \param nlh pointer to the netlink message * \param buflen size of buffer which stores the message * \param type netlink attribute type that you want to add * \param len netlink attribute payload length * \param data pointer to the data that will be stored by the new attribute * * This function first checks that the data can be added to the message * (fits into the buffer) and then updates the length field of the Netlink * message (nlmsg_len) by adding the size (header + payload) of the new * attribute. The function returns true if the attribute could be added * to the message, otherwise false is returned. */ bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data) { if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen) return false; mnl_attr_put(nlh, type, len, data); return true; }
/** * mnl_nlmsg_put_header - reserve and prepare room for Netlink header * \param buf memory already allocated to store the Netlink header * * This function sets to zero the room that is required to put the Netlink * header in the memory buffer passed as parameter. This function also * initializes the nlmsg_len field to the size of the Netlink header. This * function returns a pointer to the Netlink header structure. */ struct nlmsghdr *mnl_nlmsg_put_header(void *buf) { int len = MNL_ALIGN(sizeof(struct nlmsghdr)); struct nlmsghdr *nlh = buf; memset(buf, 0, len); nlh->nlmsg_len = len; return nlh; }
/** * mnl_attr_nest_start - start an attribute nest * \param nlh pointer to the netlink message * \param type netlink attribute type * * This function adds the attribute header that identifies the beginning of * an attribute nest. This function always returns a valid pointer to the * beginning of the nest. */ struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type) { struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh); /* set start->nla_len in mnl_attr_nest_end() */ start->nla_type = NLA_F_NESTED | type; nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr)); return start; }
static ssize_t send_netlink_json(uint8_t *snd_buf, struct json_object *parsed_obj, int32_t sock_fd, struct sockaddr *netlink_addr) { struct nlmsghdr *netlink_hdr = (struct nlmsghdr*) snd_buf; const char *json_str = json_object_to_json_string_ext(parsed_obj, JSON_C_TO_STRING_PLAIN); socklen_t netlink_addrlen = sizeof(netlink_addr); memcpy(netlink_hdr + 1, json_str, strlen(json_str) + 1); netlink_hdr->nlmsg_len = mnl_nlmsg_size(MNL_ALIGN(strlen(json_str))); return sendto(sock_fd, snd_buf, netlink_hdr->nlmsg_len, 0, netlink_addr, netlink_addrlen); }
/** * mnl_attr_next - get the next attribute in the payload of a netlink message * \param attr pointer to the current attribute * * This function returns a pointer to the next attribute after the one passed * as parameter. You have to use mnl_attr_ok() to ensure that the next * attribute is valid. */ struct nlattr *mnl_attr_next(const struct nlattr *attr) { return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len)); }
/** * mnl_nlmsg_get_payload_tail - get the ending of the netlink message * \param nlh pointer to netlink message * * This function returns a pointer to the netlink message tail. This is useful * to build a message since we continue adding attributes at the end of the * message. */ void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh) { return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len); }
/** * mnl_nlmsg_next - get the next netlink message in a multipart message * \param nlh current netlink message that we are handling * \param len length of the remaining bytes in the buffer (passed by reference). * * This function returns a pointer to the next netlink message that is part * of a multi-part netlink message. Netlink can batch several messages into * one buffer so that the receiver has to iterate over the whole set of * Netlink messages. * * You have to use mnl_nlmsg_ok() to check if the next Netlink message is * valid. */ struct nlmsghdr * mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len) { *len -= MNL_ALIGN(nlh->nlmsg_len); return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len)); }
/** * mnl_nlmsg_get_payload_offset - get a pointer to the payload of the message * \param nlh pointer to a netlink header * \param offset offset to the payload of the attributes TLV set * * This function returns a pointer to the payload of the netlink message plus * a given offset. */ void * mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset) { return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); }