Compiling ynl.c in a C++ code base requires invoking C compiler and using extern "C" for the headers. To make it easier, we can add small changes to the ynl.c file to make it palatable to the native C++ compiler. The changes are: - avoid using void* pointer arithmetic, use char* instead - avoid implicit void* type casts, add c-style explicit casts - avoid implicit int->enum type casts, add c-style explicit casts - avoid anonymous structs (for type casts) - namespacify cpp version, this should let us compile both ynl.c as c and ynl.c as cpp in the same binary (YNL_CPP can be used to enable/disable namespacing) Also add test_cpp rule to make sure ynl.c won't break C++ in the future. Signed-off-by: Stanislav Fomichev --- tools/net/ynl/lib/Makefile | 5 +++- tools/net/ynl/lib/ynl-priv.h | 11 ++++++- tools/net/ynl/lib/ynl.c | 58 +++++++++++++++++++++--------------- tools/net/ynl/lib/ynl.h | 19 +++++++++--- 4 files changed, 63 insertions(+), 30 deletions(-) diff --git a/tools/net/ynl/lib/Makefile b/tools/net/ynl/lib/Makefile index 4b2b98704ff9..94f8dc4a31d1 100644 --- a/tools/net/ynl/lib/Makefile +++ b/tools/net/ynl/lib/Makefile @@ -11,7 +11,7 @@ OBJS=$(patsubst %.c,%.o,${SRCS}) include $(wildcard *.d) -all: ynl.a +all: ynl.a test_cpp ynl.a: $(OBJS) @echo -e "\tAR $@" @@ -23,6 +23,9 @@ ynl.a: $(OBJS) distclean: clean rm -f *.a +test_cpp: ynl.c + $(COMPILE.cpp) -DYNL_CPP -o ynl.cc.o $< + %.o: %.c $(COMPILE.c) -MMD -c -o $@ $< diff --git a/tools/net/ynl/lib/ynl-priv.h b/tools/net/ynl/lib/ynl-priv.h index 824777d7e05e..1dbb14e760e6 100644 --- a/tools/net/ynl/lib/ynl-priv.h +++ b/tools/net/ynl/lib/ynl-priv.h @@ -6,6 +6,10 @@ #include #include +#if defined(__cplusplus) && defined(YNL_CPP) +namespace ynl_cpp { +#endif + struct ynl_parse_arg; /* @@ -224,7 +228,7 @@ static inline void *ynl_attr_data_end(const struct nlattr *attr) #define ynl_attr_for_each_payload(start, len, attr) \ for ((attr) = ynl_attr_first(start, len, 0); attr; \ - (attr) = ynl_attr_next(start + len, attr)) + (attr) = ynl_attr_next((char *)start + len, attr)) static inline struct nlattr * ynl_attr_if_good(const void *end, struct nlattr *attr) @@ -467,4 +471,9 @@ ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data) else ynl_attr_put_s64(nlh, type, data); } + +#if defined(__cplusplus) && defined(YNL_CPP) +} // namespace ynl_cpp +#endif + #endif diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c index 2a169c3c0797..9155b4d5b9f9 100644 --- a/tools/net/ynl/lib/ynl.c +++ b/tools/net/ynl/lib/ynl.c @@ -11,6 +11,10 @@ #include "ynl.h" +#if defined(__cplusplus) && defined(YNL_CPP) +namespace ynl_cpp { +#endif + #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*arr)) #define __yerr_msg(yse, _msg...) \ @@ -23,13 +27,13 @@ } \ }) -#define __yerr_code(yse, _code...) \ - ({ \ - struct ynl_error *_yse = (yse); \ - \ - if (_yse) { \ - _yse->code = _code; \ - } \ +#define __yerr_code(yse, _code...) \ + ({ \ + struct ynl_error *_yse = (yse); \ + \ + if (_yse) { \ + _yse->code = (enum ynl_error_code)_code; \ + } \ }) #define __yerr(yse, _code, _msg...) \ @@ -149,7 +153,7 @@ ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off, return n; } - data_len = end - start; + data_len = (char *)end - (char *)start; ynl_attr_for_each_payload(start, data_len, attr) { astart_off = (char *)attr - (char *)start; @@ -192,7 +196,7 @@ ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off, off -= sizeof(struct nlattr); start = ynl_attr_data(attr); - end = start + ynl_attr_data_len(attr); + end = (char *)start + ynl_attr_data_len(attr); return n + ynl_err_walk(ys, start, end, off, next_pol, &str[n], str_sz - n, nest_pol); @@ -325,12 +329,12 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh, static int ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) { - const struct nlmsgerr *err = ynl_nlmsg_data(nlh); + const struct nlmsgerr *err = (struct nlmsgerr *)ynl_nlmsg_data(nlh); unsigned int hlen; int code; code = err->error >= 0 ? err->error : -err->error; - yarg->ys->err.code = code; + yarg->ys->err.code = (enum ynl_error_code)code; errno = code; hlen = sizeof(*err); @@ -348,7 +352,7 @@ static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) err = *(int *)NLMSG_DATA(nlh); if (err < 0) { - yarg->ys->err.code = -err; + yarg->ys->err.code = (enum ynl_error_code)-err; errno = -err; ynl_ext_ack_check(yarg->ys, nlh, sizeof(int)); @@ -366,7 +370,7 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr) unsigned int type, len; unsigned char *data; - data = ynl_attr_data(attr); + data = (unsigned char *)ynl_attr_data(attr); len = ynl_attr_data_len(attr); type = ynl_attr_type(attr); if (type > yarg->rsp_policy->max_attr) { @@ -463,7 +467,7 @@ int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name, static void ynl_err_reset(struct ynl_sock *ys) { - ys->err.code = 0; + ys->err.code = YNL_ERROR_NONE; ys->err.attr_offs = 0; ys->err.msg[0] = 0; } @@ -643,8 +647,8 @@ ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts) if (!ys->n_mcast_groups) return 0; - ys->mcast_groups = calloc(ys->n_mcast_groups, - sizeof(*ys->mcast_groups)); + ys->mcast_groups = (struct ynl_sock_mcast *)calloc( + ys->n_mcast_groups, sizeof(*ys->mcast_groups)); if (!ys->mcast_groups) return YNL_PARSE_CB_ERROR; @@ -741,7 +745,8 @@ ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse) int sock_type; int one = 1; - ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE); + ys = (struct ynl_sock *)malloc(sizeof(*ys) + + 2 * YNL_SOCKET_BUFFER_SIZE); if (!ys) return NULL; memset(ys, 0, sizeof(*ys)); @@ -878,7 +883,7 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh) } else { struct genlmsghdr *gehdr; - gehdr = ynl_nlmsg_data(nlh); + gehdr = (struct genlmsghdr *)ynl_nlmsg_data(nlh); cmd = gehdr->cmd; } @@ -888,7 +893,7 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh) if (!info->cb) return YNL_PARSE_CB_ERROR; - rsp = calloc(1, info->alloc_sz); + rsp = (struct ynl_ntf_base_type *)calloc(1, info->alloc_sz); rsp->free = info->free; yarg.data = rsp->data; yarg.rsp_policy = info->policy; @@ -933,7 +938,8 @@ int ynl_ntf_check(struct ynl_sock *ys) /* YNL specific helpers used by the auto-generated code */ -struct ynl_dump_list_type *YNL_LIST_END = (void *)(0xb4d123); +struct ynl_dump_list_type *YNL_LIST_END = + (struct ynl_dump_list_type *)(void *)(0xb4d123); void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd) { @@ -962,7 +968,7 @@ ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd) return -1; } - gehdr = ynl_nlmsg_data(nlh); + gehdr = (struct genlmsghdr *)ynl_nlmsg_data(nlh); if (gehdr->cmd != rsp_cmd) return ynl_ntf_parse(ys, nlh); } @@ -973,7 +979,7 @@ ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd) static int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg) { - struct ynl_req_state *yrs = (void *)yarg; + struct ynl_req_state *yrs = (struct ynl_req_state *)yarg; int ret; ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd); @@ -1006,7 +1012,7 @@ int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh, static int ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data) { - struct ynl_dump_state *ds = (void *)data; + struct ynl_dump_state *ds = (struct ynl_dump_state *)data; struct ynl_dump_list_type *obj; struct ynl_parse_arg yarg = {}; int ret; @@ -1015,7 +1021,7 @@ ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data) if (ret) return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK; - obj = calloc(1, ds->alloc_sz); + obj = (struct ynl_dump_list_type *)calloc(1, ds->alloc_sz); if (!obj) return YNL_PARSE_CB_ERROR; @@ -1066,3 +1072,7 @@ int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh, yds->first = ynl_dump_end(yds); return -1; } + +#if defined(__cplusplus) && defined(YNL_CPP) +} // namespace ynl_cpp +#endif diff --git a/tools/net/ynl/lib/ynl.h b/tools/net/ynl/lib/ynl.h index db7c0591a63f..47a8652f056f 100644 --- a/tools/net/ynl/lib/ynl.h +++ b/tools/net/ynl/lib/ynl.h @@ -9,6 +9,10 @@ #include "ynl-priv.h" +#if defined(__cplusplus) && defined(YNL_CPP) +namespace ynl_cpp { +#endif + enum ynl_error_code { YNL_ERROR_NONE = 0, __YNL_ERRNO_END = 4096, @@ -56,6 +60,11 @@ struct ynl_family { unsigned int ntf_info_size; }; +struct ynl_sock_mcast { + unsigned int id; + char name[GENL_NAMSIZ]; +}; + /** * struct ynl_sock - YNL wrapped netlink socket * @err: YNL error descriptor, cleared on every request. @@ -71,10 +80,7 @@ struct ynl_sock { __u16 family_id; unsigned int n_mcast_groups; - struct { - unsigned int id; - char name[GENL_NAMSIZ]; - } *mcast_groups; + struct ynl_sock_mcast *mcast_groups; struct ynl_ntf_base_type *ntf_first; struct ynl_ntf_base_type **ntf_last_next; @@ -140,4 +146,9 @@ static inline bool ynl_has_ntf(struct ynl_sock *ys) struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys); void ynl_ntf_free(struct ynl_ntf_base_type *ntf); + +#if defined(__cplusplus) && defined(YNL_CPP) +} // namespace ynl_cpp +#endif + #endif -- 2.50.1