X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-rtnl%2Frtnl-message.c;h=cfb2af31420a37fae42df25c4c968bb25dc171bd;hp=84ebf65d8ebab93f430cf52a9fb47f454101ebf9;hb=2263bb9a92f25571f837700cfee4fb79721baf46;hpb=20dff6c4ff4f6e1b88c841e523ce9cff0e150fdf diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c index 84ebf65d8..cfb2af314 100644 --- a/src/libsystemd/sd-rtnl/rtnl-message.c +++ b/src/libsystemd/sd-rtnl/rtnl-message.c @@ -114,6 +114,24 @@ int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char pr return 0; } +int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + if ((rtm->rtm_family == AF_INET && prefixlen > 32) || + (rtm->rtm_family == AF_INET6 && prefixlen > 128)) + return -ERANGE; + + rtm->rtm_src_len = prefixlen; + + return 0; +} + int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) { struct rtmsg *rtm; @@ -143,6 +161,36 @@ int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) { return 0; } +int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(dst_len, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *dst_len = rtm->rtm_dst_len; + + return 0; +} + +int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(src_len, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *src_len = rtm->rtm_src_len; + + return 0; +} + int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol) { @@ -150,7 +198,8 @@ int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret, int r; assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL); - assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL); + assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) || + rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL); assert_return(ret, -EINVAL); r = message_new(rtnl, ret, nlmsg_type); @@ -171,6 +220,58 @@ int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret, return 0; } +int sd_rtnl_message_neigh_set_flags(sd_rtnl_message *m, uint8_t flags) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + ndm->ndm_flags |= flags; + + return 0; +} + +int sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + ndm->ndm_state |= state; + + return 0; +} + +int sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + *flags = ndm->ndm_flags; + + return 0; +} + +int sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + *state = ndm->ndm_state; + + return 0; +} + int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) { struct ndmsg *ndm; @@ -206,7 +307,9 @@ int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlm int r; assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL); - assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL); + assert_return(ndm_family == AF_INET || + ndm_family == AF_INET6 || + ndm_family == PF_BRIDGE, -EINVAL); assert_return(ret, -EINVAL); r = message_new(rtnl, ret, nlmsg_type); @@ -651,8 +754,8 @@ int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const size = (size_t)r; if (size) { - length = strnlen(data, size); - if (length >= size) + length = strnlen(data, size+1); + if (length > size) return -EINVAL; } else length = strlen(data); @@ -1145,13 +1248,20 @@ uint32_t rtnl_message_get_serial(sd_rtnl_message *m) { return m->hdr->nlmsg_seq; } +int sd_rtnl_message_is_error(sd_rtnl_message *m) { + assert_return(m, 0); + assert_return(m->hdr, 0); + + return m->hdr->nlmsg_type == NLMSG_ERROR; +} + int sd_rtnl_message_get_errno(sd_rtnl_message *m) { struct nlmsgerr *err; assert_return(m, -EINVAL); assert_return(m->hdr, -EINVAL); - if (m->hdr->nlmsg_type != NLMSG_ERROR) + if (!sd_rtnl_message_is_error(m)) return 0; err = NLMSG_DATA(m->hdr); @@ -1253,6 +1363,8 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool /* from the kernel */ if (ucred->uid == 0 && ucred->pid == 0) auth = true; + else + log_debug("rtnl: ignoring message from uid %u pid %u", ucred->uid, ucred->pid); } else if (cmsg->cmsg_level == SOL_NETLINK && cmsg->cmsg_type == NETLINK_PKTINFO && cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) { @@ -1331,7 +1443,7 @@ int socket_read_message(sd_rtnl *rtnl) { } } - for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) { + for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) { _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; const NLType *nl_type; @@ -1346,7 +1458,8 @@ int socket_read_message(sd_rtnl *rtnl) { if (new_msg->nlmsg_type == NLMSG_DONE) { /* finished reading multi-part message */ done = true; - break; + + continue; } /* check that we support this message type */