xioopen() checks r/w mode of addresses
diff --git a/CHANGES b/CHANGES
index 63a4362..df39858 100644
--- a/CHANGES
+++ b/CHANGES
@@ -156,6 +156,10 @@
 	INTERFACE addresses did not accept options of INTERFACE group (for
 	historical reasons they were only available with TUN addresses).
 
+	Opening addresses did not check if they support all directions expected
+	by Socat. Now an error is printed when, e.g,, a read-only type address
+	is opened for writing.
+
 Coding:
 	Introduced groups_t instead of uint32_t, for more flexibility.
 
diff --git a/doc/socat.yo b/doc/socat.yo
index 350ef4f..a8e6a6b 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -296,8 +296,9 @@
 label(ADDRESS_CREAT)dit(bf(tt(CREATE:<filename>)))
    Opens link(<filename>)(TYPE_FILENAME) with code(creat()) and uses the file
    descriptor for writing. 
-   This address type requires write-only context, because a file opened with
-   code(creat) cannot be read from. nl()
+   This is a write-only address because a file opened with code(creat) cannot
+   be read from. See options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).nl()
    Flags like O_LARGEFILE cannot be applied. If you need them use
    link(OPEN)(ADDRESS_OPEN) with options
    link(create)(OPTION_O_CREAT),link(create)(OPTION_O_TRUNC). nl()
@@ -480,7 +481,8 @@
 label(ADDRESS_IP_RECV)dit(bf(tt(IP-RECV:<protocol>)))
    Opens a raw IP socket of link(<protocol>)(TYPE_PROTOCOL). Depending on option link(pf)(OPTION_PROTOCOL_FAMILY), IP protocol version
    4 or 6 is used. It receives packets from multiple unspecified peers and merges the data.
-   No replies are possible.
+   No replies are possible, this is a read-only address, see options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).
    It can be, e.g., addressed by socat IP-SENDTO address peers.
    Protocol 255 uses the raw socket with the IP header being part of the
    data.nl()
@@ -1014,10 +1016,14 @@
 
 label(ADDRESS_STDERR)dit(bf(tt(STDERR)))
    Uses file descriptor 2.nl()
+   This is a write-only address, see options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).nl()
    Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
    See also: link(FD)(ADDRESS_FD)
 label(ADDRESS_STDIN)dit(bf(tt(STDIN)))
    Uses file descriptor 0.nl()
+   This is a read-only address, see options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).nl()
    Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
    Useful options:
    link(readbytes)(OPTION_READBYTES)nl()
@@ -1030,6 +1036,8 @@
    See also: link(FD)(ADDRESS_FD)
 label(ADDRESS_STDOUT)dit(bf(tt(STDOUT)))
    Uses file descriptor 1.nl()
+   This is a write-only address, see options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).nl()
    Option groups: link(FD)(GROUP_FD) (link(TERMIOS)(GROUP_TERMIOS),link(REG)(GROUP_REG),link(SOCKET)(GROUP_SOCKET)) nl()
    See also: link(FD)(ADDRESS_FD)
 label(ADDRESS_SYSTEM)dit(bf(tt(SYSTEM:<shell-command>)))
@@ -1326,7 +1334,11 @@
    Creates a UDP socket on <port> [link(UDP service)(TYPE_UDP_SERVICE)] using UDP/IP version 4 or 6
    depending on option link(pf)(OPTION_PROTOCOL_FAMILY).
    It receives packets from multiple unspecified peers and merges the data.
-   No replies are possible. It works well with, e.g., socat link(UDP-SENDTO)(ADDRESS_UDP_SENDTO) address peers; it behaves similar to a syslog server.nl()
+   No replies are possible. It works well with, e.g., socat
+   link(UDP-SENDTO)(ADDRESS_UDP_SENDTO) address peers; it behaves similar to a
+   syslog server.nl()
+   This is a read-only address, see options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).nl()
    Note: if you need the link(fork)(OPTION_FORK) option, use link(UDP-RECVFROM)(ADDRESS_UDP_RECVFROM) in unidirectional mode (with link(option -u)(option_u)) instead.nl()
    Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(IP4)(GROUP_IP4),link(IP6)(GROUP_IP6),link(RANGE)(GROUP_RANGE) nl()
    Useful options:
@@ -1426,7 +1438,9 @@
 label(ADDRESS_UNIX_RECV)dit(bf(tt(UNIX-RECV:<filename>)))
    Creates a unixdomain() datagram socket [link(<filename>)(TYPE_FILENAME)].
    Receives packets from multiple unspecified peers and merges the data.
-   No replies are possible. It can be, e.g., addressed by socat UNIX-SENDTO address peers.
+   No replies are possible, this is a read-only address, see options link(-u)(option_u) and
+   link(-U)(option_U), and link(dual addresses)(ADDRESS_DUAL).
+   It can be, e.g., addressed by socat UNIX-SENDTO address peers.
    It behaves similar to a syslog server.nl()
    Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(NAMED)(GROUP_NAMED),link(UNIX)(GROUP_SOCK_UNIX) nl()
    See also:
diff --git a/test.sh b/test.sh
index 944d6f1..bf2be0e 100755
--- a/test.sh
+++ b/test.sh
@@ -3526,6 +3526,7 @@
 if [ -z "$NAMEKEYW" ] || [[ "$NAMEKEYW" == \#* ]]; then continue; fi
 
 export ts="$td/test$N.socket"
+case $RUNS in tcp4|tcp6) newport $RUNS;; esac
 WAITTMPL="$(echo "$WAITTMPL" |sed -e 's/\040/ /g')"
 TESTADDR=$(eval echo $TESTTMPL)
 PEERADDR=$(eval echo $PEERTMPL)
@@ -3542,11 +3543,11 @@
 # connecting socat  brings the result of od
 if ! eval $NUMCOND; then :;
 elif [ "$FEAT" != ',' ] && ! testfeats "$FEAT" >/dev/null; then
-    $PRINTF "test $F_n $TEST... ${YELLOW}$FEAT not available${NORMAL}\n" $N
+    $PRINTF "test $F_n $TEST... ${YELLOW}Feature $FEAT not configured${NORMAL}\n" $N
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
 elif ! runs$RUNS >/dev/null; then
-    $PRINTF "test $F_n $TEST... ${YELLOW}$RUNS not available${NORMAL}\n" $N
+    $PRINTF "test $F_n $TEST... ${YELLOW}$RUNS not available$ on host${NORMAL}\n" $N
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
 else
@@ -16882,11 +16883,7 @@
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
 elif ! runsip4 >/dev/null; then
-    $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
-    numCANT=$((numCANT+1))
-    listCANT="$listCANT $N"
-elif ! runsip4 >/dev/null; then
-    $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
+    $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available on host${NORMAL}\n" $N
     numCANT=$((numCANT+1))
     listCANT="$listCANT $N"
 elif [ -z "$FOREIGN" ]; then
diff --git a/xio-creat.c b/xio-creat.c
index de5faac..e5b197a 100644
--- a/xio-creat.c
+++ b/xio-creat.c
@@ -17,7 +17,7 @@
 
 
 /*! within stream model, this is a write-only address - use 2 instead of 3 */
-const struct addrdesc xioaddr_creat  = { "CREATE", 3, xioopen_creat, GROUP_FD|GROUP_NAMED|GROUP_FILE, 0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_creat  = { "CREATE", 1+XIO_WRONLY, xioopen_creat, GROUP_FD|GROUP_NAMED|GROUP_FILE, 0, 0, 0 HELP(":<filename>") };
 
 
 /* retrieve the mode option and perform the creat() call.
diff --git a/xio-rawip.c b/xio-rawip.c
index 9bad320..fe05e95 100644
--- a/xio-rawip.c
+++ b/xio-rawip.c
@@ -39,23 +39,23 @@
 			  struct opt *opts, int xioflags,
 			  xiofile_t *xxfd, groups_t groups, int *pf);
 
-const struct addrdesc xioaddr_rawip_sendto  = { "IP-SENDTO",      3, xioopen_rawip_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
-const struct addrdesc xioaddr_rawip_datagram= { "IP-DATAGRAM",    3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
-const struct addrdesc xioaddr_rawip_recvfrom= { "IP-RECVFROM",    3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
-const struct addrdesc xioaddr_rawip_recv    = { "IP-RECV",        1, xioopen_rawip_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE,             PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc xioaddr_rawip_sendto  = { "IP-SENDTO",      1+XIO_RDWR,   xioopen_rawip_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc xioaddr_rawip_datagram= { "IP-DATAGRAM",    1+XIO_RDWR,   xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc xioaddr_rawip_recvfrom= { "IP-RECVFROM",    1+XIO_RDWR,   xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc xioaddr_rawip_recv    = { "IP-RECV",        1+XIO_RDONLY, xioopen_rawip_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE,             PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
 
 #if WITH_IP4
-const struct addrdesc xioaddr_rawip4_sendto  = { "IP4-SENDTO",     3, xioopen_rawip_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
-const struct addrdesc xioaddr_rawip4_datagram= { "IP4-DATAGRAM",   3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
-const struct addrdesc xioaddr_rawip4_recvfrom= { "IP4-RECVFROM",   3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_CHILD|GROUP_RANGE, PF_INET,  SOCK_RAW, 0 HELP(":<protocol>") };
-const struct addrdesc xioaddr_rawip4_recv    = { "IP4-RECV",       1, xioopen_rawip_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE,             PF_INET,  SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc xioaddr_rawip4_sendto  = { "IP4-SENDTO",     1+XIO_RDWR,   xioopen_rawip_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc xioaddr_rawip4_datagram= { "IP4-DATAGRAM",   1+XIO_RDWR,   xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc xioaddr_rawip4_recvfrom= { "IP4-RECVFROM",   1+XIO_RDWR,   xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_CHILD|GROUP_RANGE, PF_INET,  SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc xioaddr_rawip4_recv    = { "IP4-RECV",       1+XIO_RDONLY, xioopen_rawip_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE,             PF_INET,  SOCK_RAW, 0 HELP(":<protocol>") };
 #endif
 
 #if WITH_IP6
-const struct addrdesc xioaddr_rawip6_sendto  = { "IP6-SENDTO",     3, xioopen_rawip_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
-const struct addrdesc xioaddr_rawip6_datagram= { "IP6-DATAGRAM",   3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
-const struct addrdesc xioaddr_rawip6_recvfrom= { "IP6-RECVFROM",   3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
-const struct addrdesc xioaddr_rawip6_recv    = { "IP6-RECV",       1, xioopen_rawip_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE,             PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc xioaddr_rawip6_sendto  = { "IP6-SENDTO",     1+XIO_RDWR,   xioopen_rawip_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc xioaddr_rawip6_datagram= { "IP6-DATAGRAM",   1+XIO_RDWR,   xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
+const struct addrdesc xioaddr_rawip6_recvfrom= { "IP6-RECVFROM",   1+XIO_RDWR,   xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
+const struct addrdesc xioaddr_rawip6_recv    = { "IP6-RECV",       1+XIO_RDONLY, xioopen_rawip_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE,             PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
 #endif
 
 
diff --git a/xio-socket.c b/xio-socket.c
index e2397b8..26eda94 100644
--- a/xio-socket.c
+++ b/xio-socket.c
@@ -79,14 +79,14 @@
 
 #if WITH_GENERICSOCKET
 /* generic socket addresses */
-const struct addrdesc xioaddr_socket_connect = { "SOCKET-CONNECT",     1, xioopen_socket_connect,  GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<remote-address>") };
+const struct addrdesc xioaddr_socket_connect = { "SOCKET-CONNECT",     1+XIO_RDWR,   xioopen_socket_connect,  GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<remote-address>") };
 #if WITH_LISTEN
-const struct addrdesc xioaddr_socket_listen  = { "SOCKET-LISTEN",      1, xioopen_socket_listen,   GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_RANGE|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<local-address>") };
+const struct addrdesc xioaddr_socket_listen  = { "SOCKET-LISTEN",      1+XIO_RDWR,   xioopen_socket_listen,   GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_RANGE|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<domain>:<protocol>:<local-address>") };
 #endif /* WITH_LISTEN */
-const struct addrdesc xioaddr_socket_sendto  = { "SOCKET-SENDTO",      3, xioopen_socket_sendto,   GROUP_FD|GROUP_SOCKET,                         0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
-const struct addrdesc xioaddr_socket_datagram= { "SOCKET-DATAGRAM",    3, xioopen_socket_datagram, GROUP_FD|GROUP_SOCKET|GROUP_RANGE,             0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
-const struct addrdesc xioaddr_socket_recvfrom= { "SOCKET-RECVFROM",    3, xioopen_socket_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_RANGE|GROUP_CHILD, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
-const struct addrdesc xioaddr_socket_recv    = { "SOCKET-RECV",        1, xioopen_socket_recv,     GROUP_FD|GROUP_SOCKET|GROUP_RANGE,             0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
+const struct addrdesc xioaddr_socket_sendto  = { "SOCKET-SENDTO",      1+XIO_RDWR,   xioopen_socket_sendto,   GROUP_FD|GROUP_SOCKET,                         0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
+const struct addrdesc xioaddr_socket_datagram= { "SOCKET-DATAGRAM",    1+XIO_RDWR,   xioopen_socket_datagram, GROUP_FD|GROUP_SOCKET|GROUP_RANGE,             0, 0, 0 HELP(":<domain>:<type>:<protocol>:<remote-address>") };
+const struct addrdesc xioaddr_socket_recvfrom= { "SOCKET-RECVFROM",    1+XIO_RDWR,   xioopen_socket_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_RANGE|GROUP_CHILD, 0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
+const struct addrdesc xioaddr_socket_recv    = { "SOCKET-RECV",        1+XIO_RDONLY, xioopen_socket_recv,     GROUP_FD|GROUP_SOCKET|GROUP_RANGE,             0, 0, 0 HELP(":<domain>:<type>:<protocol>:<local-address>") };
 #endif /* WITH_GENERICSOCKET */
 
 
diff --git a/xio-udp.c b/xio-udp.c
index 5992da2..6c4d4c6 100644
--- a/xio-udp.c
+++ b/xio-udp.c
@@ -42,35 +42,35 @@
 			int xioflags, xiofile_t *xxfd, groups_t groups,
 			int pf, int socktype, int ipproto);
 
-const struct addrdesc xioaddr_udp_connect  = { "UDP-CONNECT",    3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp_connect  = { "UDP-CONNECT",    1+XIO_RDWR,   xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") };
 #if WITH_LISTEN
-const struct addrdesc xioaddr_udp_listen   = { "UDP-LISTEN", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") };
+const struct addrdesc xioaddr_udp_listen   = { "UDP-LISTEN",     1+XIO_RDWR,   xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") };
 #endif /* WITH_LISTEN */
-const struct addrdesc xioaddr_udp_sendto   = { "UDP-SENDTO",   3, xioopen_udp_sendto,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
-const struct addrdesc xioaddr_udp_recvfrom = { "UDP-RECVFROM",   3, xioopen_udp_recvfrom,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
-const struct addrdesc xioaddr_udp_recv     = { "UDP-RECV",       1, xioopen_udp_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE,             PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
-const struct addrdesc xioaddr_udp_datagram = { "UDP-DATAGRAM", 3, xioopen_udp_datagram,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp_sendto   = { "UDP-SENDTO",     1+XIO_RDWR,   xioopen_udp_sendto,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp_recvfrom = { "UDP-RECVFROM",   1+XIO_RDWR,   xioopen_udp_recvfrom,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
+const struct addrdesc xioaddr_udp_recv     = { "UDP-RECV",       1+XIO_RDONLY, xioopen_udp_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE,             PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
+const struct addrdesc xioaddr_udp_datagram = { "UDP-DATAGRAM",   1+XIO_RDWR,   xioopen_udp_datagram,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
 
 #if WITH_IP4
-const struct addrdesc xioaddr_udp4_connect  = { "UDP4-CONNECT",    3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp4_connect = { "UDP4-CONNECT",   1+XIO_RDWR,   xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET HELP(":<host>:<port>") };
 #if WITH_LISTEN
-const struct addrdesc xioaddr_udp4_listen   = { "UDP4-LISTEN", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET, IPPROTO_UDP, PF_INET HELP(":<port>") };
+const struct addrdesc xioaddr_udp4_listen  = { "UDP4-LISTEN",    1+XIO_RDWR,   xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET, IPPROTO_UDP, PF_INET HELP(":<port>") };
 #endif /* WITH_LISTEN */
-const struct addrdesc xioaddr_udp4_sendto   = { "UDP4-SENDTO",     3, xioopen_udp_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, PF_INET, SOCK_DGRAM, IPPROTO_UDP  HELP(":<host>:<port>") };
-const struct addrdesc xioaddr_udp4_datagram = { "UDP4-DATAGRAM",3, xioopen_udp_datagram,  GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
-const struct addrdesc xioaddr_udp4_recvfrom = { "UDP4-RECVFROM",   3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
-const struct addrdesc xioaddr_udp4_recv     = { "UDP4-RECV",       1, xioopen_udp_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE,             PF_INET, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
+const struct addrdesc xioaddr_udp4_sendto  = { "UDP4-SENDTO",    1+XIO_RDWR,   xioopen_udp_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, PF_INET, SOCK_DGRAM, IPPROTO_UDP  HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp4_datagram = { "UDP4-DATAGRAM", 1+XIO_RDWR,   xioopen_udp_datagram,  GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp4_recvfrom= { "UDP4-RECVFROM",  1+XIO_RDWR,   xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
+const struct addrdesc xioaddr_udp4_recv    = { "UDP4-RECV",      1+XIO_RDONLY, xioopen_udp_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE,             PF_INET, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
 #endif /* WITH_IP4 */
 
 #if WITH_IP6
-const struct addrdesc xioaddr_udp6_connect  = { "UDP6-CONNECT",    3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET6 HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp6_connect = { "UDP6-CONNECT",   1+XIO_RDWR,   xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET6 HELP(":<host>:<port>") };
 #if WITH_LISTEN
-const struct addrdesc xioaddr_udp6_listen   = { "UDP6-LISTEN", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET6, IPPROTO_UDP, 0 HELP(":<port>") };
+const struct addrdesc xioaddr_udp6_listen  = { "UDP6-LISTEN",    1+XIO_RDWR,   xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET6, IPPROTO_UDP, 0 HELP(":<port>") };
 #endif /* WITH_LISTEN */
-const struct addrdesc xioaddr_udp6_sendto   = { "UDP6-SENDTO",     3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
-const struct addrdesc xioaddr_udp6_datagram = { "UDP6-DATAGRAM",   3, xioopen_udp_datagram,GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
-const struct addrdesc xioaddr_udp6_recvfrom = { "UDP6-RECVFROM",   3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
-const struct addrdesc xioaddr_udp6_recv     = { "UDP6-RECV",       1, xioopen_udp_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE,             PF_INET6, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
+const struct addrdesc xioaddr_udp6_sendto  = { "UDP6-SENDTO",    1+XIO_RDWR,   xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp6_datagram= { "UDP6-DATAGRAM",  1+XIO_RDWR,   xioopen_udp_datagram,GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
+const struct addrdesc xioaddr_udp6_recvfrom= { "UDP6-RECVFROM",  1+XIO_RDWR,   xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
+const struct addrdesc xioaddr_udp6_recv    = { "UDP6-RECV",      1+XIO_RDONLY, xioopen_udp_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE,             PF_INET6, SOCK_DGRAM, IPPROTO_UDP  HELP(":<port>") };
 #endif /* WITH_IP6 */
 
 
diff --git a/xio-unix.c b/xio-unix.c
index 1952c75..f5d6263 100644
--- a/xio-unix.c
+++ b/xio-unix.c
@@ -38,23 +38,23 @@
 /* the first free parameter is 0 for "normal" unix domain sockets, or 1 for
    abstract unix sockets (Linux); the second and third free parameter are
    unsused */
-const struct addrdesc xioaddr_unix_connect = { "UNIX-CONNECT",  3, xioopen_unix_connect,  GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_unix_connect = { "UNIX-CONNECT",  1+XIO_RDWR,   xioopen_unix_connect,  GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
 #if WITH_LISTEN
-const struct addrdesc xioaddr_unix_listen  = { "UNIX-LISTEN",   3, xioopen_unix_listen,   GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_unix_listen  = { "UNIX-LISTEN",   1+XIO_RDWR,   xioopen_unix_listen,   GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<filename>") };
 #endif /* WITH_LISTEN */
-const struct addrdesc xioaddr_unix_sendto  = { "UNIX-SENDTO",   3, xioopen_unix_sendto,   GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
-const struct addrdesc xioaddr_unix_recvfrom= { "UNIX-RECVFROM", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD,              0, 0, 0 HELP(":<filename>") };
-const struct addrdesc xioaddr_unix_recv    = { "UNIX-RECV",     1, xioopen_unix_recv,     GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
-const struct addrdesc xioaddr_unix_client  = { "UNIX-CLIENT",   3, xioopen_unix_client,   GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_unix_sendto  = { "UNIX-SENDTO",   1+XIO_RDWR,   xioopen_unix_sendto,   GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_unix_recvfrom= { "UNIX-RECVFROM", 1+XIO_RDWR,   xioopen_unix_recvfrom, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD,              0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_unix_recv    = { "UNIX-RECV",     1+XIO_RDONLY, xioopen_unix_recv,     GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_unix_client  = { "UNIX-CLIENT",   1+XIO_RDWR,   xioopen_unix_client,   GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          0, 0, 0 HELP(":<filename>") };
 #if WITH_ABSTRACT_UNIXSOCKET
-const struct addrdesc xioaddr_abstract_connect = { "ABSTRACT-CONNECT",  3, xioopen_unix_connect,  GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_connect = { "ABSTRACT-CONNECT",  1+XIO_RDWR,   xioopen_unix_connect,  GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
 #if WITH_LISTEN
-const struct addrdesc xioaddr_abstract_listen  = { "ABSTRACT-LISTEN",   3, xioopen_unix_listen,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_listen  = { "ABSTRACT-LISTEN",   1+XIO_RDWR,   xioopen_unix_listen,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<filename>") };
 #endif /* WITH_LISTEN */
-const struct addrdesc xioaddr_abstract_sendto  = { "ABSTRACT-SENDTO",   3, xioopen_unix_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
-const struct addrdesc xioaddr_abstract_recvfrom= { "ABSTRACT-RECVFROM", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD,              1, 0, 0 HELP(":<filename>") };
-const struct addrdesc xioaddr_abstract_recv    = { "ABSTRACT-RECV",     1, xioopen_unix_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
-const struct addrdesc xioaddr_abstract_client  = { "ABSTRACT-CLIENT",   3, xioopen_unix_client,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_sendto  = { "ABSTRACT-SENDTO",   1+XIO_RDWR,   xioopen_unix_sendto,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_recvfrom= { "ABSTRACT-RECVFROM", 1+XIO_RDWR,   xioopen_unix_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD,              1, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_recv    = { "ABSTRACT-RECV",     1+XIO_RDONLY, xioopen_unix_recv,     GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
+const struct addrdesc xioaddr_abstract_client  = { "ABSTRACT-CLIENT",   1+XIO_RDWR,   xioopen_unix_client,   GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY,                          1, 0, 0 HELP(":<filename>") };
 #endif /* WITH_ABSTRACT_UNIXSOCKET */
 
 const struct optdesc xioopt_unix_tightsocklen = { "unix-tightsocklen",    "tightsocklen",  OPT_UNIX_TIGHTSOCKLEN,  GROUP_SOCK_UNIX, PH_PREBIND, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.un.tight), XIO_SIZEOF(para.socket.un.tight) };
diff --git a/xioopen.c b/xioopen.c
index ca93f88..7a49811 100644
--- a/xioopen.c
+++ b/xioopen.c
@@ -603,6 +603,7 @@
 int xioopen_single(xiofile_t *xfd, int xioflags) {
    struct single *sfd = &xfd->stream;
    const struct addrdesc *addrdesc;
+   const char *modetext[4] = { "none", "read-only", "write-only", "read-write" } ;
    int result;
    /* Values to be saved until xioopen() is finished */
 #if HAVE_RESOLV_H
@@ -642,6 +643,11 @@
       return STAT_NORETRY;
 #endif /* HAVE_RESOLV_H */
 
+   addrdesc = xfd->stream.addr;
+   /* Check if address supports required data directions */
+   if (((xioflags+1)&XIO_ACCMODE) & ~(addrdesc->directions)) {
+      Warn2("address is opened in %s mode but only supports %s", modetext[(xioflags+1)&XIO_ACCMODE], modetext[addrdesc->directions]);
+   }
    if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) {
       xfd->tag = XIO_TAG_RDONLY;
    } else if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) {
@@ -653,7 +659,6 @@
    }
    xfd->stream.flags     &= (~XIO_ACCMODE);
    xfd->stream.flags     |= (xioflags & XIO_ACCMODE);
-   addrdesc = xfd->stream.addr;
    result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv,
 			      xfd->stream.opts, xioflags, xfd,
 			      addrdesc->groups, addrdesc->arg1,