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


Hi!

I've verified this patch on 2.4 kernel and when portmap is not running (or
is running but ypbind is not) and domainname is set, nsswitch.conf has
hosts: files nisplus nis dns, gethostbyname returns immediately what I'm
asking for, while without this patch it takes eons before it gives correct
answer.
Ulrich, could you please consider this patch or tell me what you don't like
on it? Thanks.

> 2001-01-09  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* sunrpc/clnt_udp.c (clntudp_bufcreate): Set IP_RECVERR on the
> 	UDP socket.
> 	(clntudp_call): Handle MSG_ERRQUEUE.
> 	* sysdeps/generic/bits/errqueue.h: New.
> 	* sysdeps/unix/sysv/linux/bits/errqueue.h: New.
> 
> --- libc/sunrpc/clnt_udp.c.jj	Tue Aug  3 19:20:26 1999
> +++ libc/sunrpc/clnt_udp.c	Tue Jan  9 18:51:32 2001
> @@ -51,6 +51,11 @@ static char sccsid[] = "@(#)clnt_udp.c 1
>  #include <rpc/pmap_clnt.h>
>  #include <net/if.h>
>  
> +#ifdef IP_RECVERR
> +#include <bits/errqueue.h>
> +#include <sys/uio.h>
> +#endif
> +
>  extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
>  extern u_long _create_xid (void);
>  
> @@ -186,6 +191,12 @@ clntudp_bufcreate (struct sockaddr_in *r
>        (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
>        /* the sockets rpc controls are non-blocking */
>        (void) __ioctl (*sockp, FIONBIO, (char *) &dontblock);
> +#ifdef IP_RECVERR
> +      {
> +	int on = 1;
> +	setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on));
> +      }
> +#endif
>        cu->cu_closeit = TRUE;
>      }
>    else
> @@ -361,6 +372,47 @@ send_again:
>  	  cu->cu_error.re_errno = errno;
>  	  return (cu->cu_error.re_status = RPC_CANTRECV);
>  	}
> +#ifdef IP_RECVERR
> +      if (fd.revents & POLLERR)
> +	{
> +	  struct msghdr msg;
> +	  struct cmsghdr *cmsg;
> +	  struct sock_extended_err *e;
> +	  struct sockaddr_in err_addr;
> +	  struct iovec iov;
> +	  char *cbuf = (char *) alloca (outlen + 256);
> +	  int ret;
> +
> +	  iov.iov_base = cbuf + 256;
> +	  iov.iov_len = outlen;
> +	  msg.msg_name = (void *) &err_addr;
> +	  msg.msg_namelen = sizeof (err_addr);
> +	  msg.msg_iov = &iov;
> +	  msg.msg_iovlen = 1;
> +	  msg.msg_flags = 0;
> +	  msg.msg_control = cbuf;
> +	  msg.msg_controllen = 256;
> +	  ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE);
> +	  if ((ret == 0
> +	       || (ret == outlen
> +		   && memcmp (cbuf + 256, cu->cu_outbuf, outlen) == 0))
> +	      && (msg.msg_flags & MSG_ERRQUEUE)
> +	      && (msg.msg_namelen == 0
> +		  || (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)))
> +	    for (cmsg = CMSG_FIRSTHDR (&msg); cmsg;
> +		 cmsg = CMSG_NXTHDR (&msg, cmsg))
> +	      if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
> +		{
> +		  e = (struct sock_extended_err *) CMSG_DATA(cmsg);
> +		  cu->cu_error.re_errno = e->ee_errno;
> +		  return (cu->cu_error.re_status = RPC_CANTRECV);
> +		}
> +	}
> +#endif
>        do
>  	{
>  	  fromlen = sizeof (struct sockaddr);
> --- libc/sysdeps/generic/bits/errqueue.h.jj	Tue Jan  9 15:57:13 2001
> +++ libc/sysdeps/generic/bits/errqueue.h	Tue Jan  9 16:00:42 2001
> @@ -0,0 +1,7 @@
> +#ifndef _BITS_ERRQUEUE_H
> +#define _BITS_ERRQUEUE_H  1
> +
> +/* This platform does not support socket error reporting
> +   via MSG_ERRQUEUE.  */
> +
> +#endif /* bits/errqueue.h */
> --- libc/sysdeps/unix/sysv/linux/bits/errqueue.h.jj	Tue Jan  9 16:01:43 2001
> +++ libc/sysdeps/unix/sysv/linux/bits/errqueue.h	Tue Jan  9 16:25:13 2001
> @@ -0,0 +1,46 @@
> +/* Copyright (C) 2000 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Library General Public License as
> +   published by the Free Software Foundation; either version 2 of the
> +   License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Library General Public License for more details.
> +
> +   You should have received a copy of the GNU Library General Public
> +   License along with the GNU C Library; see the file COPYING.LIB.  If not,
> +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
> +   Boston, MA 02111-1307, USA.  */
> +
> +/* Linux version.  */
> +
> +#ifndef _BITS_ERRQUEUE_H
> +#define _BITS_ERRQUEUE_H  1
> +
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +
> +struct sock_extended_err
> +  {
> +    u_int32_t ee_errno;
> +    u_int8_t ee_origin;
> +    u_int8_t ee_type;
> +    u_int8_t ee_code;
> +    u_int8_t ee_pad;
> +    u_int32_t ee_info;
> +    u_int32_t ee_data;
> +  };
> +
> +#define SO_EE_ORIGIN_NONE  0
> +#define SO_EE_ORIGIN_LOCAL 1
> +#define SO_EE_ORIGIN_ICMP  2
> +#define SO_EE_ORIGIN_ICMP6 3
> +
> +#define SO_EE_OFFENDER(see)	\
> +  ((struct sockaddr *)(((struct sock_extended_err)(see))+1))
> +
> +#endif /* bits/errqueue.h */
> 
> 	Jakub

	Jakub

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]