TESTREQ - MSG_TRUNC on Linux 2.6.21 or older
Roy Marples
Thu Jul 15 07:03:35 2010Hi List Attached is a patch to address netlink messagses > 256 bytes, which now happens on new Linux kernels. I don't want to allocate an 8k buffer, so trying to work out the size using MSG_PEEK | MSG_TRUNC. However, recv(2) shows this only works on 2.6.22 kernels or newer. So, can anyone apply this patch to dhcpcd-5.2.6 and test it on a 2.6.21 or older kernel and attach the output of dhcpcd -dB please? Thanks Roy
diff --git a/if-linux.c b/if-linux.c
index ab1bbe6..9856204 100644
--- a/if-linux.c
+++ b/if-linux.c
@@ -54,8 +54,6 @@
#include "dhcp.h"
#include "net.h"
-#define BUFFERLEN 256
-
static int sock_fd;
static struct sockaddr_nl sock_nl;
@@ -144,14 +142,33 @@ static int
get_netlink(int fd, int flags,
int (*callback)(struct nlmsghdr *))
{
- char *buffer = NULL;
- ssize_t bytes;
+ char *buf = NULL, *nbuf;
+ ssize_t buflen = 0, bytes;
struct nlmsghdr *nlm;
int r = -1;
- buffer = xzalloc(sizeof(char) * BUFFERLEN);
for (;;) {
- bytes = recv(fd, buffer, BUFFERLEN, flags);
+ errno = 0;
+ bytes = recv(fd, NULL, 0,
+ flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC);
+ printf ("recv test, bytes=%zd errno=%d\n", bytes, errno);
+ if (bytes == -1) {
+ if (errno == EAGAIN) {
+ r = 0;
+ goto eexit;
+ }
+ if (errno == EINTR)
+ continue;
+ goto eexit;
+ }
+ if (buflen < bytes) {
+ buflen = bytes;
+ nbuf = realloc(buf, buflen);
+ if (nbuf == NULL)
+ goto eexit;
+ buf = nbuf;
+ }
+ bytes = recv(fd, buf, buflen, flags);
if (bytes == -1) {
if (errno == EAGAIN) {
r = 0;
@@ -161,7 +178,7 @@ get_netlink(int fd, int flags,
continue;
goto eexit;
}
- for (nlm = (struct nlmsghdr *)buffer;
+ for (nlm = (struct nlmsghdr *)buf;
NLMSG_OK(nlm, (size_t)bytes);
nlm = NLMSG_NEXT(nlm, bytes))
{
@@ -172,7 +189,7 @@ get_netlink(int fd, int flags,
}
eexit:
- free(buffer);
+ free(buf);
return r;
}
Archive administrator: postmaster@marples.name