diff options
Diffstat (limited to 'tools/net/ynl/lib/ynl.c')
-rw-r--r-- | tools/net/ynl/lib/ynl.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c index 86729119e1ef..b9e77af5af5f 100644 --- a/tools/net/ynl/lib/ynl.c +++ b/tools/net/ynl/lib/ynl.c @@ -404,9 +404,33 @@ struct nlmsghdr *ynl_msg_start(struct ynl_sock *ys, __u32 id, __u16 flags) nlh->nlmsg_flags = flags; nlh->nlmsg_seq = ++ys->seq; + /* This is a local YNL hack for length checking, we put the buffer + * length in nlmsg_pid, since messages sent to the kernel always use + * PID 0. Message needs to be terminated with ynl_msg_end(). + */ + nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZE; + return nlh; } +static int ynl_msg_end(struct ynl_sock *ys, struct nlmsghdr *nlh) +{ + /* We stash buffer length in nlmsg_pid. */ + if (nlh->nlmsg_pid == 0) { + yerr(ys, YNL_ERROR_INPUT_INVALID, + "Unknown input buffer length"); + return -EINVAL; + } + if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW) { + yerr(ys, YNL_ERROR_INPUT_TOO_BIG, + "Constructred message longer than internal buffer"); + return -EMSGSIZE; + } + + nlh->nlmsg_pid = 0; + return 0; +} + struct nlmsghdr * ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags, __u8 cmd, __u8 version) @@ -561,6 +585,7 @@ ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts) ys->mcast_groups[i].name[GENL_NAMSIZ - 1] = 0; } } + i++; } return 0; @@ -606,6 +631,10 @@ static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name) nlh = ynl_gemsg_start_req(ys, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1); ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY_NAME, family_name); + err = ynl_msg_end(ys, nlh); + if (err < 0) + return err; + err = send(ys->socket, nlh, nlh->nlmsg_len, 0); if (err < 0) { perr(ys, "failed to request socket family info"); @@ -867,6 +896,10 @@ int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh, { int err; + err = ynl_msg_end(ys, req_nlh); + if (err < 0) + return err; + err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0); if (err < 0) return err; @@ -920,6 +953,10 @@ int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh, { int err; + err = ynl_msg_end(ys, req_nlh); + if (err < 0) + return err; + err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0); if (err < 0) return err; |