Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150540064
D38947.id118571.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D38947.id118571.diff
View Options
diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h
--- a/sys/netlink/netlink_snl.h
+++ b/sys/netlink/netlink_snl.h
@@ -124,6 +124,7 @@
struct linear_buffer *lb;
};
#define SCRATCH_BUFFER_SIZE 1024
+#define SNL_WRITER_BUFFER_SIZE 256
typedef void snl_parse_field_f(struct snl_state *ss, void *hdr, void *target);
struct snl_field_parser {
@@ -294,6 +295,30 @@
return (hdr);
}
+static inline struct nlmsghdr *
+snl_read_reply(struct snl_state *ss, uint32_t nlmsg_seq)
+{
+ while (true) {
+ struct nlmsghdr *hdr = snl_read_message(ss);
+ if (hdr == NULL)
+ break;
+ if (hdr->nlmsg_seq == nlmsg_seq)
+ return (hdr);
+ }
+
+ return (NULL);
+}
+
+static inline struct nlmsghdr *
+snl_get_reply(struct snl_state *ss, struct nlmsghdr *hdr)
+{
+ uint32_t nlmsg_seq = hdr->nlmsg_seq;
+
+ if (snl_send(ss, hdr, hdr->nlmsg_len))
+ return (snl_read_reply(ss, nlmsg_seq));
+ return (NULL);
+}
+
/*
* Checks that attributes are sorted by attribute type.
*/
@@ -511,4 +536,303 @@
*((uint32_t *)target) = *((uint32_t *)src);
}
+struct snl_errmsg_data {
+ uint32_t nlmsg_seq;
+ int error;
+ char *error_str;
+ uint32_t error_offs;
+ struct nlattr *cookie;
+};
+#define _IN(_field) offsetof(struct nlmsgerr, _field)
+#define _OUT(_field) offsetof(struct snl_errmsg_data, _field)
+static const struct snl_attr_parser nla_p_errmsg[] = {
+ { .type = NLMSGERR_ATTR_MSG, .off = _OUT(error_str), .cb = snl_attr_get_string },
+ { .type = NLMSGERR_ATTR_OFFS, .off = _OUT(error_offs), .cb = snl_attr_get_uint32 },
+ { .type = NLMSGERR_ATTR_COOKIE, .off = _OUT(cookie), .cb = snl_attr_get_nla },
+};
+
+static const struct snl_field_parser nlf_p_errmsg[] = {
+ { .off_in = _IN(error), .off_out = _OUT(error), .cb = snl_field_get_uint32 },
+ { .off_in = _IN(msg.nlmsg_seq), .off_out = _OUT(nlmsg_seq), .cb = snl_field_get_uint32 },
+};
+#undef _IN
+#undef _OUT
+SNL_DECLARE_PARSER(snl_errmsg_parser, struct nlmsgerr, nlf_p_errmsg, nla_p_errmsg);
+
+static inline bool
+snl_check_return(struct snl_state *ss, struct nlmsghdr *hdr, struct snl_errmsg_data *e)
+{
+ if (hdr != NULL && hdr->nlmsg_type == NLMSG_ERROR)
+ return (snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e));
+ return (false);
+}
+
+/* writer logic */
+struct snl_writer {
+ char *base;
+ uint32_t offset;
+ uint32_t size;
+ struct nlmsghdr *hdr;
+ struct snl_state *ss;
+ bool error;
+};
+
+static inline void
+snl_init_writer(struct snl_state *ss, struct snl_writer *nw)
+{
+ nw->size = SNL_WRITER_BUFFER_SIZE;
+ nw->base = snl_allocz(ss, nw->size);
+ if (nw->base == NULL) {
+ nw->error = true;
+ nw->size = 0;
+ }
+
+ nw->offset = 0;
+ nw->hdr = NULL;
+ nw->error = false;
+ nw->ss = ss;
+}
+
+static inline bool
+snl_realloc_msg_buffer(struct snl_writer *nw, size_t sz)
+{
+ uint32_t new_size = nw->size * 2;
+
+ while (new_size < nw->size + sz)
+ new_size *= 2;
+
+ if (nw->error)
+ return (false);
+
+ void *new_base = snl_allocz(nw->ss, new_size);
+ if (new_base == NULL) {
+ nw->error = true;
+ return (false);
+ }
+
+ memcpy(new_base, nw->base, nw->offset);
+ if (nw->hdr != NULL) {
+ int hdr_off = (char *)(nw->hdr) - nw->base;
+ nw->hdr = (struct nlmsghdr *)(void *)((char *)new_base + hdr_off);
+ }
+ nw->base = new_base;
+
+ return (true);
+}
+
+static inline void *
+snl_reserve_msg_data_raw(struct snl_writer *nw, size_t sz)
+{
+ sz = NETLINK_ALIGN(sz);
+
+ if (__predict_false(nw->offset + sz > nw->size)) {
+ if (!snl_realloc_msg_buffer(nw, sz))
+ return (NULL);
+ }
+
+ void *data_ptr = &nw->base[nw->offset];
+ nw->offset += sz;
+
+ return (data_ptr);
+}
+#define snl_reserve_msg_object(_ns, _t) ((_t *)snl_reserve_msg_data_raw(_ns, sizeof(_t)))
+#define snl_reserve_msg_data(_ns, _sz, _t) ((_t *)snl_reserve_msg_data_raw(_ns, _sz))
+
+static inline void *
+_snl_reserve_msg_attr(struct snl_writer *nw, uint16_t nla_type, uint16_t sz)
+{
+ sz += sizeof(struct nlattr);
+
+ struct nlattr *nla = snl_reserve_msg_data(nw, sz, struct nlattr);
+ if (__predict_false(nla == NULL))
+ return (NULL);
+ nla->nla_type = nla_type;
+ nla->nla_len = sz;
+
+ return ((void *)(nla + 1));
+}
+#define snl_reserve_msg_attr(_ns, _at, _t) ((_t *)_snl_reserve_msg_attr(_ns, _at, sizeof(_t)))
+
+static inline bool
+snl_add_msg_attr(struct snl_writer *nw, int attr_type, int attr_len, const void *data)
+{
+ int required_len = NLA_ALIGN(attr_len + sizeof(struct nlattr));
+
+ if (__predict_false(nw->offset + required_len > nw->size)) {
+ if (!snl_realloc_msg_buffer(nw, required_len))
+ return (false);
+ }
+
+ struct nlattr *nla = (struct nlattr *)(&nw->base[nw->offset]);
+
+ nla->nla_len = attr_len + sizeof(struct nlattr);
+ nla->nla_type = attr_type;
+ if (attr_len > 0) {
+ if ((attr_len % 4) != 0) {
+ /* clear padding bytes */
+ bzero((char *)nla + required_len - 4, 4);
+ }
+ memcpy((nla + 1), data, attr_len);
+ }
+ nw->offset += required_len;
+ return (true);
+}
+
+static inline bool
+snl_add_msg_attr_raw(struct snl_writer *nw, const struct nlattr *nla_src)
+{
+ int attr_len = nla_src->nla_len - sizeof(struct nlattr);
+
+ assert(attr_len >= 0);
+
+ return (snl_add_msg_attr(nw, nla_src->nla_type, attr_len, (const void *)(nla_src + 1)));
+}
+
+static inline bool
+snl_add_msg_attr_u8(struct snl_writer *nw, int attrtype, uint8_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(uint8_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_u16(struct snl_writer *nw, int attrtype, uint16_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(uint16_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_u32(struct snl_writer *nw, int attrtype, uint32_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(uint32_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_u64(struct snl_writer *nw, int attrtype, uint64_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(uint64_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_s8(struct snl_writer *nw, int attrtype, int8_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(int8_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_s16(struct snl_writer *nw, int attrtype, int16_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(int16_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_s32(struct snl_writer *nw, int attrtype, int32_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(int32_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_s64(struct snl_writer *nw, int attrtype, int64_t value)
+{
+ return (snl_add_msg_attr(nw, attrtype, sizeof(int64_t), &value));
+}
+
+static inline bool
+snl_add_msg_attr_flag(struct snl_writer *nw, int attrtype)
+{
+ return (snl_add_msg_attr(nw, attrtype, 0, NULL));
+}
+
+static inline bool
+snl_add_msg_attr_string(struct snl_writer *nw, int attrtype, const char *str)
+{
+ return (snl_add_msg_attr(nw, attrtype, strlen(str) + 1, str));
+}
+
+
+static inline int
+snl_get_msg_offset(const struct snl_writer *nw)
+{
+ return (nw->offset - ((char *)nw->hdr - nw->base));
+}
+
+static inline void *
+_snl_restore_msg_offset(const struct snl_writer *nw, int off)
+{
+ return ((void *)((char *)nw->hdr + off));
+}
+#define snl_restore_msg_offset(_ns, _off, _t) ((_t *)_snl_restore_msg_offset(_ns, _off))
+
+static inline int
+snl_add_msg_attr_nested(struct snl_writer *nw, int attrtype)
+{
+ int off = snl_get_msg_offset(nw);
+ struct nlattr *nla = snl_reserve_msg_data(nw, sizeof(struct nlattr), struct nlattr);
+ if (__predict_false(nla == NULL))
+ return (0);
+ nla->nla_type = attrtype;
+ return (off);
+}
+
+static inline void
+snl_end_attr_nested(const struct snl_writer *nw, int off)
+{
+ if (!nw->error) {
+ struct nlattr *nla = snl_restore_msg_offset(nw, off, struct nlattr);
+ nla->nla_len = NETLINK_ALIGN(snl_get_msg_offset(nw) - off);
+ }
+}
+
+static inline struct nlmsghdr *
+snl_create_msg_request(struct snl_writer *nw, int nlmsg_type)
+{
+ assert(nw->hdr == NULL);
+
+ struct nlmsghdr *hdr = snl_reserve_msg_object(nw, struct nlmsghdr);
+ hdr->nlmsg_type = nlmsg_type;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ nw->hdr = hdr;
+
+ return (hdr);
+}
+
+static void
+snl_abort_msg(struct snl_writer *nw)
+{
+ if (nw->hdr != NULL) {
+ int offset = (char *)(&nw->base[nw->offset]) - (char *)(nw->hdr);
+
+ nw->offset -= offset;
+ nw->hdr = NULL;
+ }
+}
+
+static inline struct nlmsghdr *
+snl_finalize_msg(struct snl_writer *nw)
+{
+ if (nw->error)
+ snl_abort_msg(nw);
+ if (nw->hdr != NULL) {
+ struct nlmsghdr *hdr = nw->hdr;
+
+ int offset = (char *)(&nw->base[nw->offset]) - (char *)(nw->hdr);
+ hdr->nlmsg_len = offset;
+ hdr->nlmsg_seq = snl_get_seq(nw->ss);
+ nw->hdr = NULL;
+
+ return (hdr);
+ }
+ return (NULL);
+}
+
+static bool
+snl_send_msgs(struct snl_writer *nw)
+{
+ int offset = nw->offset;
+
+ assert(nw->hdr == NULL);
+ nw->offset = 0;
+
+ return (snl_send(nw->ss, nw->base, offset));
+}
+
#endif
diff --git a/sys/netlink/netlink_snl_route.h b/sys/netlink/netlink_snl_route.h
--- a/sys/netlink/netlink_snl_route.h
+++ b/sys/netlink/netlink_snl_route.h
@@ -127,4 +127,40 @@
return (false);
}
+static inline bool
+snl_add_msg_attr_ip(struct snl_writer *nw, int attrtype, const struct sockaddr *sa)
+{
+ const void *addr;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ addr = &((const struct sockaddr_in *)sa)->sin_addr;
+ return (snl_add_msg_attr(nw, attrtype, 4, addr));
+ case AF_INET6:
+ addr = &((const struct sockaddr_in6 *)sa)->sin6_addr;
+ return (snl_add_msg_attr(nw, attrtype, 16, addr));
+ }
+
+ return (false);
+}
+
+static inline bool
+snl_add_msg_attr_ipvia(struct snl_writer *nw, int attrtype, const struct sockaddr *sa)
+{
+ char buf[17];
+
+ buf[0] = sa->sa_family;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ memcpy(&buf[1], &((const struct sockaddr_in *)sa)->sin_addr, 4);
+ return (snl_add_msg_attr(nw, attrtype, 5, buf));
+ case AF_INET6:
+ memcpy(&buf[1], &((const struct sockaddr_in6 *)sa)->sin6_addr, 16);
+ return (snl_add_msg_attr(nw, attrtype, 17, buf));
+ }
+
+ return (false);
+}
+
#endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 3, 4:38 AM (16 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30744214
Default Alt Text
D38947.id118571.diff (9 KB)
Attached To
Mode
D38947: netlink: add snl writer
Attached
Detach File
Event Timeline
Log In to Comment