linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Read all data from socket in do_get_nl_link
@ 2012-08-01 12:57 Alexander Stein
  0 siblings, 0 replies; only message in thread
From: Alexander Stein @ 2012-08-01 12:57 UTC (permalink / raw)
  To: linux-can; +Cc: Alexander Stein

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.stein@systec-electronic.com>
---
Without that patch I only get the data for lo, eth0 and eth2 (I printed
RTA_DATA(tb[IFLA_IFNAME]))), even eth1 is missing here.
With that patch I get the data for all my 10 interfaces I currently have.

 src/libsocketcan.c |  231 +++++++++++++++++++++++++++-------------------------
 1 files changed, 119 insertions(+), 112 deletions(-)

diff --git a/src/libsocketcan.c b/src/libsocketcan.c
index 26da338..b3815c1 100644
--- a/src/libsocketcan.c
+++ b/src/libsocketcan.c
@@ -258,6 +258,7 @@ static int open_nl_sock()
 	int fd;
 	int sndbuf = 32768;
 	int rcvbuf = 32768;
+	int flags;
 	unsigned int addr_len;
 	struct sockaddr_nl local;
 
@@ -271,6 +272,10 @@ static int open_nl_sock()
 
 	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;
 	local.nl_groups = 0;
@@ -349,43 +354,40 @@ 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;
-	}
+	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;
+		}
 
-	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;
+		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];
+			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);
+			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 (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 (tb[IFLA_LINKINFO])
+				parse_rtattr_nested(linkinfo,
+						    IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+			else
+				continue;
 
 		if (acquire == GET_XSTATS) {
 			if (!linkinfo[IFLA_INFO_XSTATS])
@@ -398,92 +400,97 @@ static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res)
 			continue;
 		}
 
-		if (!linkinfo[IFLA_INFO_DATA]) {
-			fprintf(stderr, "no link data found\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");
+			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");
+			parse_rtattr_nested(can_attr, IFLA_CAN_MAX,
+					    linkinfo[IFLA_INFO_DATA]);
 
-			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;
+			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");
+				}
 
-		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.8.6


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-08-01 12:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-01 12:57 [PATCH] Read all data from socket in do_get_nl_link Alexander Stein

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).