Changeset View
Changeset View
Standalone View
Standalone View
sys/netlink/netlink_snl.h
Show First 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
int off = NLMSG_HDRLEN + NETLINK_ALIGN(hdrlen); | int off = NLMSG_HDRLEN + NETLINK_ALIGN(hdrlen); | ||||
int len = hdr->nlmsg_len - off; | int len = hdr->nlmsg_len - off; | ||||
struct nlattr *nla_head = (struct nlattr *)(void *)((char *)hdr + off); | struct nlattr *nla_head = (struct nlattr *)(void *)((char *)hdr + off); | ||||
return (snl_parse_attrs_raw(ss, nla_head, len, ps, pslen, target)); | return (snl_parse_attrs_raw(ss, nla_head, len, ps, pslen, target)); | ||||
} | } | ||||
static inline bool | static inline void | ||||
snl_parse_header(struct snl_state *ss, void *hdr, int len, | snl_parse_fields(struct snl_state *ss, struct nlmsghdr *hdr, int hdrlen __unused, | ||||
const struct snl_hdr_parser *parser, void *target) | const struct snl_field_parser *ps, int pslen, void *target) | ||||
{ | { | ||||
/* Extract fields first (if any) */ | for (int i = 0; i < pslen; i++) { | ||||
for (int i = 0; i < parser->fp_size; i++) { | const struct snl_field_parser *fp = &ps[i]; | ||||
const struct snl_field_parser *fp = &parser->fp[i]; | |||||
void *src = (char *)hdr + fp->off_in; | void *src = (char *)hdr + fp->off_in; | ||||
void *dst = (char *)target + fp->off_out; | void *dst = (char *)target + fp->off_out; | ||||
fp->cb(ss, src, dst); | fp->cb(ss, src, dst); | ||||
} | } | ||||
} | |||||
static inline bool | |||||
snl_parse_header(struct snl_state *ss, void *hdr, int len, | |||||
const struct snl_hdr_parser *parser, void *target) | |||||
{ | |||||
/* Extract fields first (if any) */ | |||||
snl_parse_fields(ss, hdr, parser->hdr_off, parser->fp, parser->fp_size, target); | |||||
struct nlattr *nla_head = (struct nlattr *)(void *)((char *)hdr + parser->hdr_off); | struct nlattr *nla_head = (struct nlattr *)(void *)((char *)hdr + parser->hdr_off); | ||||
bool result = snl_parse_attrs_raw(ss, nla_head, len - parser->hdr_off, | bool result = snl_parse_attrs_raw(ss, nla_head, len - parser->hdr_off, | ||||
parser->np, parser->np_size, target); | parser->np, parser->np_size, target); | ||||
return (result); | return (result); | ||||
} | } | ||||
static inline bool | static inline bool | ||||
▲ Show 20 Lines • Show All 158 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static inline void | static inline void | ||||
snl_field_get_uint32(struct snl_state *ss __unused, void *src, void *target) | snl_field_get_uint32(struct snl_state *ss __unused, void *src, void *target) | ||||
{ | { | ||||
*((uint32_t *)target) = *((uint32_t *)src); | *((uint32_t *)target) = *((uint32_t *)src); | ||||
} | } | ||||
static inline void | |||||
snl_field_get_ptr(struct snl_state *ss __unused, void *src, void *target) | |||||
{ | |||||
*((void **)target) = src; | |||||
} | |||||
struct snl_errmsg_data { | struct snl_errmsg_data { | ||||
uint32_t nlmsg_seq; | struct nlmsghdr *orig_hdr; | ||||
int error; | int error; | ||||
char *error_str; | |||||
uint32_t error_offs; | uint32_t error_offs; | ||||
char *error_str; | |||||
struct nlattr *cookie; | struct nlattr *cookie; | ||||
}; | }; | ||||
#define _IN(_field) offsetof(struct nlmsgerr, _field) | #define _IN(_field) offsetof(struct nlmsgerr, _field) | ||||
#define _OUT(_field) offsetof(struct snl_errmsg_data, _field) | #define _OUT(_field) offsetof(struct snl_errmsg_data, _field) | ||||
static const struct snl_attr_parser nla_p_errmsg[] = { | 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_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_OFFS, .off = _OUT(error_offs), .cb = snl_attr_get_uint32 }, | ||||
{ .type = NLMSGERR_ATTR_COOKIE, .off = _OUT(cookie), .cb = snl_attr_get_nla }, | { .type = NLMSGERR_ATTR_COOKIE, .off = _OUT(cookie), .cb = snl_attr_get_nla }, | ||||
}; | }; | ||||
static const struct snl_field_parser nlf_p_errmsg[] = { | 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(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 }, | { .off_in = _IN(msg), .off_out = _OUT(orig_hdr), .cb = snl_field_get_ptr }, | ||||
}; | }; | ||||
#undef _IN | #undef _IN | ||||
#undef _OUT | #undef _OUT | ||||
SNL_DECLARE_PARSER(snl_errmsg_parser, struct nlmsgerr, nlf_p_errmsg, nla_p_errmsg); | SNL_DECLARE_PARSER(snl_errmsg_parser, struct nlmsgerr, nlf_p_errmsg, nla_p_errmsg); | ||||
#define _IN(_field) offsetof(struct nlmsgerr, _field) | #define _IN(_field) offsetof(struct nlmsgerr, _field) | ||||
#define _OUT(_field) offsetof(struct snl_errmsg_data, _field) | #define _OUT(_field) offsetof(struct snl_errmsg_data, _field) | ||||
static const struct snl_attr_parser nla_p_donemsg[] = {}; | static const struct snl_attr_parser nla_p_donemsg[] = {}; | ||||
static const struct snl_field_parser nlf_p_donemsg[] = { | static const struct snl_field_parser nlf_p_donemsg[] = { | ||||
{ .off_in = _IN(error), .off_out = _OUT(error), .cb = snl_field_get_uint32 }, | { .off_in = _IN(error), .off_out = _OUT(error), .cb = snl_field_get_uint32 }, | ||||
}; | }; | ||||
#undef _IN | #undef _IN | ||||
#undef _OUT | #undef _OUT | ||||
SNL_DECLARE_PARSER(snl_donemsg_parser, struct nlmsgerr, nlf_p_donemsg, nla_p_donemsg); | SNL_DECLARE_PARSER(snl_donemsg_parser, struct nlmsgerr, nlf_p_donemsg, nla_p_donemsg); | ||||
static inline bool | static inline bool | ||||
snl_parse_errmsg(struct snl_state *ss, struct nlmsghdr *hdr, struct snl_errmsg_data *e) | |||||
{ | |||||
if ((hdr->nlmsg_flags & NLM_F_CAPPED) != 0) | |||||
return (snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e)); | |||||
const struct snl_hdr_parser *ps = &snl_errmsg_parser; | |||||
struct nlmsgerr *errmsg = (struct nlmsgerr *)(hdr + 1); | |||||
int hdrlen = sizeof(int) + NLMSG_ALIGN(errmsg->msg.nlmsg_len); | |||||
struct nlattr *attr_head = (struct nlattr *)(void *)((char *)errmsg + hdrlen); | |||||
int attr_len = hdr->nlmsg_len - sizeof(struct nlmsghdr) - hdrlen; | |||||
snl_parse_fields(ss, (struct nlmsghdr *)errmsg, hdrlen, ps->fp, ps->fp_size, e); | |||||
return (snl_parse_attrs_raw(ss, attr_head, attr_len, ps->np, ps->np_size, e)); | |||||
} | |||||
static inline bool | |||||
snl_read_reply_code(struct snl_state *ss, uint32_t nlmsg_seq, struct snl_errmsg_data *e) | snl_read_reply_code(struct snl_state *ss, uint32_t nlmsg_seq, struct snl_errmsg_data *e) | ||||
{ | { | ||||
struct nlmsghdr *hdr = snl_read_reply(ss, nlmsg_seq); | struct nlmsghdr *hdr = snl_read_reply(ss, nlmsg_seq); | ||||
if (hdr == NULL) { | if (hdr == NULL) { | ||||
e->error = EINVAL; | e->error = EINVAL; | ||||
} else if (hdr->nlmsg_type == NLMSG_ERROR) { | } else if (hdr->nlmsg_type == NLMSG_ERROR) { | ||||
if (!snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e)) | if (!snl_parse_errmsg(ss, hdr, e)) | ||||
e->error = EINVAL; | e->error = EINVAL; | ||||
return (e->error == 0); | return (e->error == 0); | ||||
} | } | ||||
return (false); | return (false); | ||||
} | } | ||||
/* | /* | ||||
* Assumes e is zeroed | * Assumes e is zeroed | ||||
*/ | */ | ||||
static inline struct nlmsghdr * | static inline struct nlmsghdr * | ||||
snl_read_reply_multi(struct snl_state *ss, uint32_t nlmsg_seq, struct snl_errmsg_data *e) | snl_read_reply_multi(struct snl_state *ss, uint32_t nlmsg_seq, struct snl_errmsg_data *e) | ||||
{ | { | ||||
struct nlmsghdr *hdr = snl_read_reply(ss, nlmsg_seq); | struct nlmsghdr *hdr = snl_read_reply(ss, nlmsg_seq); | ||||
if (hdr == NULL) { | if (hdr == NULL) { | ||||
e->error = EINVAL; | e->error = EINVAL; | ||||
} else if (hdr->nlmsg_type == NLMSG_ERROR) { | } else if (hdr->nlmsg_type == NLMSG_ERROR) { | ||||
if (!snl_parse_nlmsg(ss, hdr, &snl_errmsg_parser, e)) | if (!snl_parse_errmsg(ss, hdr, e)) | ||||
e->error = EINVAL; | e->error = EINVAL; | ||||
} if (hdr->nlmsg_type == NLMSG_DONE) { | } if (hdr->nlmsg_type == NLMSG_DONE) { | ||||
snl_parse_nlmsg(ss, hdr, &snl_donemsg_parser, e); | snl_parse_nlmsg(ss, hdr, &snl_donemsg_parser, e); | ||||
} else | } else | ||||
return (hdr); | return (hdr); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 275 Lines • Show Last 20 Lines |