diff options
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | socket/sys/socket.h | 52 | ||||
-rw-r--r-- | sysdeps/mach/hurd/bind.c | 33 | ||||
-rw-r--r-- | sysdeps/mach/hurd/connect.c | 13 | ||||
-rw-r--r-- | sysdeps/mach/hurd/sendto.c | 11 |
5 files changed, 86 insertions, 43 deletions
@@ -1,3 +1,23 @@ +Mon Dec 25 20:56:39 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> + + * sysdeps/mach/hurd/bind.c: Translate EEXIST from dir_link into + EADDRINUSE. If translated node doesn't grok ifsock protocol, + return EADDRINUSE. + + * sysdeps/mach/hurd/connect.c: Make address arg + `const struct sockaddr_un *'. + The redecl is kosher and avoids another variable for AF_LOCAL case. + * sysdeps/mach/hurd/sendto.c: Likewise. + * sysdeps/mach/hurd/bind.c: Likewise. + + * socket/sys/socket.h (__SOCKADDR_ARG): Enable transparent_union + code for GCC >= 2.7; use __transparent_union__ for name safety; + add several sockaddr flavors. + (__SOCKADDR_ALLTYPES, __SOCKADDR_ONETYPE): New macros used in + constructing the transparent union declarations. + (__CONST_SOCKADDR_ARG): New type (or macro if not GCC 2.7). + (bind, connect, sendto): Make the sockaddr argument use that. + Fri Dec 22 00:57:38 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/mach/hurd/setgid.c: In root case, store into NEWAUX, not diff --git a/socket/sys/socket.h b/socket/sys/socket.h index 6521721..9b88e64 100644 --- a/socket/sys/socket.h +++ b/socket/sys/socket.h @@ -115,25 +115,38 @@ struct sockaddr /* This is the type we use for generic socket address arguments. - NOTE: Since this functionality is volatile, I'm disabling the use of it for - now. - - With GCC 2.6 and later, the funky union causes redeclarations or uses with + With GCC 2.7 and later, the funky union causes redeclarations or uses with any of the listed types to be allowed without complaint. */ #if (!defined (__GNUC__) || __GNUC__ < 2 || \ - /*(__GNUC__ == 2 && __GNUC_MINOR__ < 6)*/ 1) -#define __SOCKADDR_ARG struct sockaddr * + (__GNUC__ == 2 && __GNUC_MINOR__ < 7)) +#define __SOCKADDR_ARG struct sockaddr * +#define __CONST_SOCKADDR_ARG __const struct sockaddr * #else -/* Bring these names into being at top-level scope, in case they have not been - defined yet. Add more `struct sockaddr_AF' types here as necessary. */ -struct sockaddr_in; -struct sockaddr_un; -struct sockaddr_ns; -typedef union { struct sockaddr *__sa; - struct sockaddr_in *__sa_in; - struct sockaddr_un *__sa_un; - struct sockaddr_ns *__sa_ns; - } __SOCKADDR_ARG __attribute__ ((transparent_union)); +/* Add more `struct sockaddr_AF' types here as necessary. + These are all the ones I found on NetBSD and Linux. */ +#define __SOCKADDR_ALLTYPES \ + __SOCKADDR_ONETYPE (sockaddr) \ + __SOCKADDR_ONETYPE (sockaddr_at) \ + __SOCKADDR_ONETYPE (sockaddr_ax25) \ + __SOCKADDR_ONETYPE (sockaddr_dl) \ + __SOCKADDR_ONETYPE (sockaddr_eon) \ + __SOCKADDR_ONETYPE (sockaddr_in) \ + __SOCKADDR_ONETYPE (sockaddr_in6) \ + __SOCKADDR_ONETYPE (sockaddr_inarp) \ + __SOCKADDR_ONETYPE (sockaddr_ipx) \ + __SOCKADDR_ONETYPE (sockaddr_iso) \ + __SOCKADDR_ONETYPE (sockaddr_ns) \ + __SOCKADDR_ONETYPE (sockaddr_un) \ + __SOCKADDR_ONETYPE (sockaddr_x25) + +#define __SOCKADDR_ONETYPE(type) struct type *__##type##__; +typedef union { __SOCKADDR_ALLTYPES + } __SOCKADDR_ARG __attribute__ ((__transparent_union__)); +#undef __SOCKADDR_ONETYPE +#define __SOCKADDR_ONETYPE(type) __const struct type *__##type##__; +typedef union { __SOCKADDR_ALLTYPES + } __CONST_SOCKADDR_ARG __attribute__ ((__transparent_union__)); +#undef __SOCKADDR_ONETYPE #endif @@ -151,7 +164,7 @@ extern int socketpair __P ((int __domain, enum __socket_type __type, int __protocol, int __fds[2])); /* Give the socket FD the local address ADDR (which is LEN bytes long). */ -extern int bind __P ((int __fd, __SOCKADDR_ARG __addr, size_t __len)); +extern int bind __P ((int __fd, __CONST_SOCKADDR_ARG __addr, size_t __len)); /* Put the local address of FD into *ADDR and its length in *LEN. */ extern int getsockname __P ((int __fd, __SOCKADDR_ARG __addr, @@ -161,7 +174,8 @@ extern int getsockname __P ((int __fd, __SOCKADDR_ARG __addr, For connectionless socket types, just set the default address to send to and the only address from which to accept transmissions. Return 0 on success, -1 for errors. */ -extern int connect __P ((int __fd, __SOCKADDR_ARG __addr, size_t __len)); +extern int connect __P ((int __fd, + __CONST_SOCKADDR_ARG __addr, size_t __len)); /* Put the address of the peer connected to socket FD into *ADDR (which is *LEN bytes long), and its actual length into *LEN. */ @@ -192,7 +206,7 @@ extern int recv __P ((int __fd, __ptr_t __buf, size_t __n, int __flags)); /* Send N bytes of BUF on socket FD to peer at address ADDR (which is ADDR_LEN bytes long). Returns the number sent, or -1 for errors. */ extern int sendto __P ((int __fd, __ptr_t __buf, size_t __n, int __flags, - __SOCKADDR_ARG __addr, size_t __addr_len)); + __CONST_SOCKADDR_ARG __addr, size_t __addr_len)); /* Read N bytes into BUF through socket FD. If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of diff --git a/sysdeps/mach/hurd/bind.c b/sysdeps/mach/hurd/bind.c index 399c23e..11f268b 100644 --- a/sysdeps/mach/hurd/bind.c +++ b/sysdeps/mach/hurd/bind.c @@ -32,23 +32,22 @@ Cambridge, MA 02139, USA. */ /* Give the socket FD the local address ADDR (which is LEN bytes long). */ int DEFUN(bind, (fd, addr, len), - int fd AND struct sockaddr *addr AND size_t len) + int fd AND const struct sockaddr_un *addr AND size_t len) { addr_port_t aport; error_t err; - if (addr->sa_family == AF_LOCAL) + if (addr->sun_family == AF_LOCAL) { /* For the local domain, we must create a node in the filesystem using the ifsock translator and then fetch the address from it. */ - struct sockaddr_un *unaddr = (struct sockaddr_un *) addr; file_t dir, node; char name[len - offsetof (struct sockaddr_un, sun_path)], *n; - strncpy (name, unaddr->sun_path, sizeof name); + strncpy (name, addr->sun_path, sizeof name); dir = __file_name_split (name, &n); if (dir == MACH_PORT_NULL) return -1; - + /* Create a new, unlinked node in the target directory. */ err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node); @@ -56,15 +55,19 @@ DEFUN(bind, (fd, addr, len), { file_t ifsock; /* Set the node's translator to make it a local-domain socket. */ - err = __file_set_translator (node, + err = __file_set_translator (node, FS_TRANS_EXCL | FS_TRANS_SET, FS_TRANS_EXCL | FS_TRANS_SET, 0, _HURD_IFSOCK, sizeof _HURD_IFSOCK, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); if (! err) - /* Link the node, now a socket, into the target directory. */ - err = __dir_link (dir, node, n); + { + /* Link the node, now a socket, into the target directory. */ + err = __dir_link (dir, node, n); + if (err == EEXIST) + err = EADDRINUSE; + } __mach_port_deallocate (__mach_task_self (), node); if (! err) { @@ -78,8 +81,16 @@ DEFUN(bind, (fd, addr, len), } } if (! err) - /* Get the address port. */ - err = __ifsock_getsockaddr (ifsock, &aport); + { + /* Get the address port. */ + err = __ifsock_getsockaddr (ifsock, &aport); + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + /* We are not talking to /hurd/ifsock. Probably someone + came in after we linked our node, unlinked it, and + replaced it with a different node, before we did our + lookup. Treat it as if our link had failed with EEXIST. */ + err = EADDRINUSE; + } __mach_port_deallocate (__mach_task_self (), ifsock); } __mach_port_deallocate (__mach_task_self (), dir); @@ -94,7 +105,7 @@ DEFUN(bind, (fd, addr, len), ({ if (err) err = __socket_create_address (port, - addr->sa_family, + addr->sun_family, (char *) addr, len, &aport); if (! err) diff --git a/sysdeps/mach/hurd/connect.c b/sysdeps/mach/hurd/connect.c index 019d1ea..0ecf736 100644 --- a/sysdeps/mach/hurd/connect.c +++ b/sysdeps/mach/hurd/connect.c @@ -31,17 +31,16 @@ Cambridge, MA 02139, USA. */ Return 0 on success, -1 for errors. */ int DEFUN(connect, (fd, addr, len), - int fd AND struct sockaddr *addr AND size_t len) + int fd AND const struct sockaddr_un *addr AND size_t len) { error_t err; addr_port_t aport; - - if (addr->sa_family == AF_LOCAL) + + if (addr->sun_family == AF_LOCAL) { /* For the local domain, we must look up the name as a file and talk to it with the ifsock protocol. */ - struct sockaddr_un *unaddr = (struct sockaddr_un *) addr; - file_t file = __file_name_lookup (unaddr->sun_path, 0, 0); + file_t file = __file_name_lookup (addr->sun_path, 0, 0); if (file == MACH_PORT_NULL) return -1; err = __ifsock_getsockaddr (file, &aport); @@ -54,12 +53,12 @@ DEFUN(connect, (fd, addr, len), } else err = EIEIO; - + err = HURD_DPORT_USE (fd, ({ if (err) err = __socket_create_address (port, - addr->sa_family, + addr->sun_family, (char *) addr, len, &aport); if (! err) diff --git a/sysdeps/mach/hurd/sendto.c b/sysdeps/mach/hurd/sendto.c index b468ba7..3c08f19 100644 --- a/sysdeps/mach/hurd/sendto.c +++ b/sysdeps/mach/hurd/sendto.c @@ -30,18 +30,17 @@ Cambridge, MA 02139, USA. */ int DEFUN(sendto, (fd, buf, n, flags, addr, addr_len), int fd AND PTR buf AND size_t n AND int flags AND - struct sockaddr *addr AND size_t addr_len) + const struct sockaddr_un *addr AND size_t addr_len) { addr_port_t aport; error_t err; int wrote; - - if (addr->sa_family == AF_LOCAL) + + if (addr->sun_family == AF_LOCAL) { /* For the local domain, we must look up the name as a file and talk to it with the ifsock protocol. */ - struct sockaddr_un *unaddr = (struct sockaddr_un *) addr; - file_t file = __file_name_lookup (unaddr->sun_path, 0, 0); + file_t file = __file_name_lookup (addr->sun_path, 0, 0); if (file == MACH_PORT_NULL) return -1; err = __ifsock_getsockaddr (file, &aport); @@ -60,7 +59,7 @@ DEFUN(sendto, (fd, buf, n, flags, addr, addr_len), ({ if (err) err = __socket_create_address (port, - addr->sa_family, + addr->sun_family, (char *) addr, addr_len, &aport); |