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]

Re: [PATCH] Make glibc sunrpc work with 2.4 unconnected UDP port error handling


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]