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

Reply via email to