recvmsg might not return all interface data at once. Use a non-blocking socket and read several times until there is no more data.
Signed-off-by: Alexander Stein <alexander.st...@systec-electronic.com> --- Not sure where exactly to put this. src/libsocketcan.c | 247 +++++++++++++++++++++++++++------------------------- 1 files changed, 130 insertions(+), 117 deletions(-) diff --git a/src/libsocketcan.c b/src/libsocketcan.c index 2ac3f2a..dcdece0 100644 --- a/src/libsocketcan.c +++ b/src/libsocketcan.c @@ -257,6 +257,7 @@ static int open_nl_sock() int fd; int sndbuf = 32768; int rcvbuf = 32768; + int flags; unsigned int addr_len; struct sockaddr_nl local; @@ -269,6 +270,10 @@ static int open_nl_sock() setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf, sizeof(sndbuf)); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf)); + + if (-1 == (flags = fcntl(fd, F_GETFL, 0))) + flags = 0; + fcntl(fd, F_SETFL, flags | O_NONBLOCK); memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; @@ -348,130 +353,138 @@ static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res) return ret; } - if ((msglen = recvmsg(fd, &msg, 0)) <= 0) { - perror("Receive error"); - return ret; - } - size_t u_msglen = (size_t) msglen; - /* Check to see if the buffers in msg get truncated */ - if (msg.msg_namelen != sizeof(peer) || - (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { - fprintf(stderr, "Uhoh... truncated message.\n"); - return ret; - } - - for (nl_msg = (struct nlmsghdr *)nlbuf; - NLMSG_OK(nl_msg, u_msglen); - nl_msg = NLMSG_NEXT(nl_msg, u_msglen)) { - int type = nl_msg->nlmsg_type; - int len; - if (type != RTM_NEWLINK) - continue; - - struct ifinfomsg *ifi = NLMSG_DATA(nl_msg); - struct rtattr *tb[IFLA_MAX + 1]; - - len = - nl_msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); - - if (strncmp - ((char *)RTA_DATA(tb[IFLA_IFNAME]), name, - sizeof(name)) != 0) - continue; - - if (tb[IFLA_LINKINFO]) - parse_rtattr_nested(linkinfo, - IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - else - continue; - - if (!linkinfo[IFLA_INFO_DATA]) { - fprintf(stderr, "no link data found\n"); + while ((msglen = recvmsg(fd, &msg, 0)) > 0) { + size_t u_msglen = (size_t) msglen; + /* Check to see if the buffers in msg get truncated */ + if (msg.msg_namelen != sizeof(peer) || + (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { + fprintf(stderr, "Uhoh... truncated message.\n"); return ret; } - parse_rtattr_nested(can_attr, IFLA_CAN_MAX, - linkinfo[IFLA_INFO_DATA]); - - switch (acquire) { - case GET_STATE: - if (can_attr[IFLA_CAN_STATE]) { - *((int *)res) = *((__u32 *) - RTA_DATA(can_attr - [IFLA_CAN_STATE])); - ret = 0; - } else { - fprintf(stderr, "no state data found\n"); + for (nl_msg = (struct nlmsghdr *)nlbuf; + NLMSG_OK(nl_msg, u_msglen); + nl_msg = NLMSG_NEXT(nl_msg, u_msglen)) { + int type = nl_msg->nlmsg_type; + int len; + printf("message type: %d\n", type); + if (type != RTM_NEWLINK) + continue; + + struct ifinfomsg *ifi = NLMSG_DATA(nl_msg); + struct rtattr *tb[IFLA_MAX + 1]; + + printf("nl_msg->nlmsg_len: %d\n", nl_msg->nlmsg_len); + len = + nl_msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + + printf("do we want interface: %s\n", (char *)RTA_DATA(tb[IFLA_IFNAME])); + if (strncmp + ((char *)RTA_DATA(tb[IFLA_IFNAME]), name, + sizeof(name)) != 0) + continue; + + if (tb[IFLA_LINKINFO]) + parse_rtattr_nested(linkinfo, + IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + else + continue; + + if (!linkinfo[IFLA_INFO_DATA]) { + fprintf(stderr, "no link data found\n"); + return ret; } - break; - case GET_RESTART_MS: - if (can_attr[IFLA_CAN_RESTART_MS]) { - *((__u32 *) res) = *((__u32 *) - RTA_DATA(can_attr - [IFLA_CAN_RESTART_MS])); - ret = 0; - } else - fprintf(stderr, "no restart_ms data found\n"); - - break; - case GET_BITTIMING: - if (can_attr[IFLA_CAN_BITTIMING]) { - memcpy(res, - RTA_DATA(can_attr[IFLA_CAN_BITTIMING]), - sizeof(struct can_bittiming)); - ret = 0; - } else - fprintf(stderr, "no bittiming data found\n"); - - break; - case GET_CTRLMODE: - if (can_attr[IFLA_CAN_CTRLMODE]) { - memcpy(res, - RTA_DATA(can_attr[IFLA_CAN_CTRLMODE]), - sizeof(struct can_ctrlmode)); - ret = 0; - } else - fprintf(stderr, "no ctrlmode data found\n"); - - break; - case GET_CLOCK: - if (can_attr[IFLA_CAN_CLOCK]) { - memcpy(res, - RTA_DATA(can_attr[IFLA_CAN_CLOCK]), - sizeof(struct can_clock)); - ret = 0; - } else - fprintf(stderr, - "no clock parameter data found\n"); - - break; - case GET_BITTIMING_CONST: - if (can_attr[IFLA_CAN_BITTIMING_CONST]) { - memcpy(res, - RTA_DATA(can_attr[IFLA_CAN_BITTIMING_CONST]), - sizeof(struct can_bittiming_const)); - ret = 0; - } else - fprintf(stderr, "no bittiming_const data found\n"); - - break; - case GET_BERR_COUNTER: - if (can_attr[IFLA_CAN_BERR_COUNTER]) { - memcpy(res, - RTA_DATA(can_attr[IFLA_CAN_BERR_COUNTER]), - sizeof(struct can_berr_counter)); - ret = 0; - } else - fprintf(stderr, "no berr_counter data found\n"); - - break; + parse_rtattr_nested(can_attr, IFLA_CAN_MAX, + linkinfo[IFLA_INFO_DATA]); + + switch (acquire) { + case GET_STATE: + if (can_attr[IFLA_CAN_STATE]) { + *((int *)res) = *((__u32 *) + RTA_DATA(can_attr + [IFLA_CAN_STATE])); + printf("state: %d\n", *((__u32 *) + RTA_DATA(can_attr + [IFLA_CAN_STATE]))); + ret = 0; + } else { + fprintf(stderr, "no state data found\n"); + } - default: - fprintf(stderr, "unknown acquire mode\n"); + break; + case GET_RESTART_MS: + if (can_attr[IFLA_CAN_RESTART_MS]) { + *((__u32 *) res) = *((__u32 *) + RTA_DATA(can_attr + [IFLA_CAN_RESTART_MS])); + ret = 0; + } else + fprintf(stderr, "no restart_ms data found\n"); + + break; + case GET_BITTIMING: + if (can_attr[IFLA_CAN_BITTIMING]) { + memcpy(res, + RTA_DATA(can_attr[IFLA_CAN_BITTIMING]), + sizeof(struct can_bittiming)); + ret = 0; + } else + fprintf(stderr, "no bittiming data found\n"); + + break; + case GET_CTRLMODE: + if (can_attr[IFLA_CAN_CTRLMODE]) { + memcpy(res, + RTA_DATA(can_attr[IFLA_CAN_CTRLMODE]), + sizeof(struct can_ctrlmode)); + ret = 0; + } else + fprintf(stderr, "no ctrlmode data found\n"); + + break; + case GET_CLOCK: + if (can_attr[IFLA_CAN_CLOCK]) { + memcpy(res, + RTA_DATA(can_attr[IFLA_CAN_CLOCK]), + sizeof(struct can_clock)); + ret = 0; + } else + fprintf(stderr, + "no clock parameter data found\n"); + + break; + case GET_BITTIMING_CONST: + if (can_attr[IFLA_CAN_BITTIMING_CONST]) { + memcpy(res, + RTA_DATA(can_attr[IFLA_CAN_BITTIMING_CONST]), + sizeof(struct can_bittiming_const)); + ret = 0; + } else + fprintf(stderr, "no bittiming_const data found\n"); + + break; + case GET_BERR_COUNTER: + if (can_attr[IFLA_CAN_BERR_COUNTER]) { + memcpy(res, + RTA_DATA(can_attr[IFLA_CAN_BERR_COUNTER]), + sizeof(struct can_berr_counter)); + ret = 0; + } else + fprintf(stderr, "no berr_counter data found\n"); + + break; + + default: + fprintf(stderr, "unknown acquire mode\n"); + } } } + if ((msglen <= 0) && (errno != EAGAIN)) { + perror("Receive error"); + } + return ret; } -- 1.7.3.4 _______________________________________________ Socketcan-core mailing list Socketcan-core@lists.berlios.de https://lists.berlios.de/mailman/listinfo/socketcan-core