summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--isys/nl.c58
2 files changed, 46 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index f033c3ed9..c2d86c3aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2007-09-13 Peter Jones <pjones@redhat.com>
+
+ * isys/nl.c (netlink_get_interface_ip, netlink_get_interface_list):
+ rewrite recvfrom() code again to work on both fedora kernels and
+ rhel ones (where MSG_TRUNC doesn't seem to work.)
+
2007-09-13 Chris Lumens <clumens@redhat.com>
* anaconda.spec: Bump version.
diff --git a/isys/nl.c b/isys/nl.c
index dec359ccf..041b2cb79 100644
--- a/isys/nl.c
+++ b/isys/nl.c
@@ -187,19 +187,30 @@ int netlink_get_interface_ip(int index, int family, void *addr) {
return ret < 0 ? -1 : 0;
}
- while ((bufsz = recvfrom(sock, NULL, 0, MSG_PEEK|MSG_TRUNC|MSG_WAITALL,
- NULL, 0)) <= 0) {
- if (bufsz < 0) {
- if (errno == EAGAIN)
- continue;
+ /* MSG_TRUNC doesn't actually seem to /work/ with netlink on RHEL 5,
+ * so we do this lame growth game until we have a buffer big enough.
+ * When we're done (which is the first time if MSG_TRUNC does its job),
+ * bufsz is the size of the message. Then we allocate a real buffer and
+ * do recvfrom again without MSG_PEEK. */
+ len = 32;
+ do {
+ len <<= 1;
+ char tmpbuf[len];
+ bufsz = recvfrom(sock, tmpbuf, len, MSG_PEEK|MSG_TRUNC|MSG_WAITALL,
+ NULL, 0);
+ if (bufsz < 0 && errno == EAGAIN)
+ bufsz = len;
+ } while (bufsz == len);
+
+ if (bufsz <= 0) {
+ if (bufsz < 0)
perror("1st recvfrom in netlink_get_interface_ip");
- }
close(sock);
- return bufsz < 0 ? -1 : 0;
+ return -1;
}
if ((buf = alloca(bufsz)) == NULL) {
- perror("calloc on msg buf in netlink_get_interface_ip");
+ perror("alloca on msg buf in netlink_get_interface_ip");
close(sock);
return -1;
}
@@ -308,19 +319,30 @@ int netlink_init_interfaces_list(void) {
return r < 0 ? -1 : r;
}
- while ((bufsz = recvfrom(sock, NULL, 0, MSG_PEEK|MSG_TRUNC|MSG_WAITALL,
- NULL, 0)) <= 0) {
- if (bufsz < 0) {
- if (errno == EAGAIN)
- continue;
- perror("1st recvfrom in netlink_get_interface_list");
- }
- close(sock);
- return bufsz < 0 ? -1 : bufsz;
+ /* MSG_TRUNC doesn't actually seem to /work/ with netlink on RHEL 5,
+ * so we do this lame growth game until we have a buffer big enough.
+ * When we're done (which is the first time if MSG_TRUNC does its job),
+ * bufsz is the size of the message. Then we allocate a real buffer and
+ * do recvfrom again without MSG_PEEK. */
+ len = 32;
+ do {
+ len <<= 1;
+ char tmpbuf[len];
+ bufsz = recvfrom(sock, tmpbuf, len, MSG_PEEK|MSG_TRUNC|MSG_WAITALL,
+ NULL, 0);
+ if (bufsz < 0 && errno == EAGAIN)
+ bufsz = len;
+ } while (bufsz == len);
+
+ if (bufsz <= 0) {
+ if (bufsz < 0)
+ perror("1st recvfrom in netlink_get_interface_list");
+ close(sock);
+ return -1;
}
if ((buf = alloca(bufsz)) == NULL) {
- perror("calloc on msg buf in netlink_get_interface_list");
+ perror("alloca on msg buf in netlink_get_interface_list");
close(sock);
return -1;
}