This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
On Wed, Jan 10, 2001 at 03:31:22PM +0100, Andreas Jaeger wrote:
> > + ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE);
> > + if ((ret == 0
> > + || (ret == outlen
> > + && memcmp (cbuf + 256, cu->cu_outbuf, outlen) == 0))
>
> Andi Kleen told me that ret == 0 doesn't make sense since that would
> mean that the error queue is empty.
I'm not sure about this, try the program below, recvmsg will return 0 but
will fill cmsg with the IP_RECVERR with ee_errno EHOSTUNREACH and other
stuff.
> The outlen check is also wrong
> since ICMP can shorten packages.
>
> He advices to use:
> if ((ret >= SUNRPC_MIN_HDR && memcpy(cbuf+256,cu->cu_outbuf,outlen) == 0)
^^^^^^ ret ??
> where SUNRPC_MIN_HDR is a minimal value we will use for comparison.
What about
if (ret >= 0 && memcpy(cbuf+256,cu->cu_outbuf,ret) == 0
&& (msg.msg_flags & MSG_ERRQUEUE)
&& ((msg.msg_namelen == 0
&& ret >= 12)
|| (msg.msg_namelen == sizeof (err_addr)
&& err_addr.sin_family == AF_INET
&& memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr,
sizeof (err_addr.sin_addr)) == 0
&& err_addr.sin_port == cu->cu_raddr.sin_port)))
?
I believe 12 is the minimal rpc header length (one LONG procedure number,
two LONGs auth_none ah_cred and ah_verf), for 2.4 kernels it is IMHO enough
to check msg_name (of course it is better to check the payload if it has
been sent back in ICMP), but for 2.2 kernels which don't fill msg_name I
believe at least those 12 bytes should be checked.
Comments?
This program prints 0 for me but fills cmsg:
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/uio.h>
int main(void)
{
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
int dontblock = 1;
char buf[56];
struct sockaddr_in sin, serr;
struct pollfd pfd;
int on, i;
socklen_t ss;
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg;
struct sock_extended_err *e;
char cbuf[8192];
on = 1;
setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on));
bindresvport (fd, (struct sockaddr_in *) 0);
ioctl (fd, FIONBIO, (char *) &dontblock);
for (i = 0; i < 56; i++)
buf[i] = '0' + i;
memset (&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(27);
sin.sin_addr.s_addr = inet_addr("207.175.42.76");
sendto (fd, buf, 56, 0, &sin, sizeof(sin));
pfd.fd = fd;
pfd.events = POLLIN;
poll(&pfd, 1, 1000);
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
msg.msg_name = (void *)&serr;
msg.msg_namelen = sizeof(serr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = cbuf;
msg.msg_controllen = 128;
memset(buf, 0, 56);
printf ("%d\n", recvmsg(fd, &msg, MSG_ERRQUEUE));
}
Jakub
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |