Index: asp3_tinet_ecnl_arm/trunk/ntshell/src/socket_stub.c
===================================================================
--- asp3_tinet_ecnl_arm/trunk/ntshell/src/socket_stub.c	(revision 375)
+++ asp3_tinet_ecnl_arm/trunk/ntshell/src/socket_stub.c	(revision 387)
@@ -62,10 +62,77 @@
 #include <netinet/tcp_var.h>
 #include <netapp/resolver.h>
-extern const ID tmax_tcp_cepid;
-#include "ff.h"
-#include "socket_stub.h"
+#include "fdtable.h"
 #include "kernel_cfg.h"
 
+#ifdef _DEBUG
+static const char THIS_FILE[] = __FILE__;
+#endif
+
 #define SOCKET_TIMEOUT 2000000
+
+struct addrinfo {
+	int ai_flags;
+	int ai_family;
+	int ai_socktype;
+	int ai_protocol;
+	socklen_t ai_addrlen;
+	struct sockaddr *ai_addr;
+	char *ai_canonname;
+	struct addrinfo *ai_next;
+};
+
+typedef uint16_t in_port_t;
+typedef uint32_t in_addr_t;
+struct in_addr { in_addr_t s_addr; };
+
+struct sockaddr_in {
+	sa_family_t sin_family;
+	in_port_t sin_port;
+	struct in_addr sin_addr;
+	uint8_t sin_zero[8];
+};
+
+struct in6_addr
+{
+	union {
+		uint8_t __s6_addr[16];
+		uint16_t __s6_addr16[8];
+		uint32_t __s6_addr32[4];
+	} __in6_union;
+};
+//#define s6_addr __in6_union.__s6_addr
+//#define s6_addr16 __in6_union.__s6_addr16
+//#define s6_addr32 __in6_union.__s6_addr32
+
+struct sockaddr_in6
+{
+	sa_family_t     sin6_family;
+	in_port_t       sin6_port;
+	uint32_t        sin6_flowinfo;
+	struct in6_addr sin6_addr;
+	uint32_t        sin6_scope_id;
+};
+
+typedef struct socket_t {
+	int family;
+	int type;
+	int protocol;
+	int cepid;
+	int repid;
+	int backlog;
+	unsigned int flags;
+	union {
+		struct sockaddr_in laddr4;
+		struct sockaddr_in6 laddr6;
+	};
+	union {
+		struct sockaddr_in raddr4;
+		struct sockaddr_in6 raddr6;
+	};
+	int buf_size;
+	unsigned char *buf;
+	void *input;
+	int len;
+} socket_t;
 
 #define tcp6_cre_cep tcp_cre_cep
@@ -82,8 +149,4 @@
 #define tcp6_set_opt tcp_set_opt
 
-#define udp6_del_cep udp_del_cep
-#define udp6_get_opt udp_get_opt
-#define udp6_set_opt udp_set_opt
-
 #ifndef SUPPORT_INET6
 
@@ -93,6 +156,9 @@
 
 ER	udp6_cre_cep (ID cepid, T_UDP6_CCEP *pk_ccep) { return E_SYS; }
+ER	udp6_del_cep (ID cepid) { return E_SYS; }
 ER_UINT	udp6_snd_dat (ID cepid, T_IPV6EP *p_dstaddr, void *data, int_t len, TMO tmout) { return E_SYS; }
 ER_UINT	udp6_rcv_dat (ID cepid, T_IPV6EP *p_dstaddr, void *data, int_t len, TMO tmout) { return E_SYS; }
+ER	udp6_set_opt (ID cepid, int_t optname, void *optval, int_t optlen) { return E_SYS; }
+ER	udp6_get_opt (ID cepid, int_t optname, void *optval, int_t optlen) { return E_SYS; }
 
 const T_IN6_ADDR *in6_get_ifaddr (int_t index) { return NULL; }
@@ -111,4 +177,5 @@
 static int tcp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg);
 static bool_t tcp_fd_readable(struct SHELL_FILE *fp);
+static bool_t tcp_fd_writable(struct SHELL_FILE *fp);
 static void tcp_fd_delete(struct SHELL_FILE *fp);
 
@@ -119,8 +186,9 @@
 static int udp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg);
 static bool_t udp_fd_readable(struct SHELL_FILE *fp);
+static bool_t udp_fd_writable(struct SHELL_FILE *fp);
 static void udp_fd_delete(struct SHELL_FILE *fp);
 
-IO_TYPE IO_TYPE_TCP = { tcp_fd_close, tcp_fd_read, tcp_fd_write, tcp_fd_seek, tcp_fd_ioctl, tcp_fd_readable, tcp_fd_delete };
-IO_TYPE IO_TYPE_UDP = { udp_fd_close, udp_fd_read, udp_fd_write, udp_fd_seek, udp_fd_ioctl, udp_fd_readable, udp_fd_delete };
+IO_TYPE IO_TYPE_TCP = { tcp_fd_close, tcp_fd_read, tcp_fd_write, tcp_fd_seek, tcp_fd_ioctl, tcp_fd_readable, tcp_fd_writable, tcp_fd_delete };
+IO_TYPE IO_TYPE_UDP = { udp_fd_close, udp_fd_read, udp_fd_write, udp_fd_seek, udp_fd_ioctl, udp_fd_readable, udp_fd_writable, udp_fd_delete };
 
 typedef struct id_table_t {
@@ -185,4 +253,15 @@
 
 #endif
+
+void addrcpy(void *_dst, const void *_src, int len)
+{
+#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
+	memcpy(_dst, _src, len);
+#else
+	uint8_t *dst = (uint8_t *)_dst, *src = &((uint8_t *)_src)[len];
+	while (src != _src)
+		*dst++ = *--src;
+#endif
+}
 
 ID new_id(id_table_t *table, int count)
@@ -347,12 +426,12 @@
 		}
 		case SOCK_DGRAM: {
-			ID cepid = new_id(udp_cepid_table, udp_cepid_table_count);
+			ID cepid = new_id(udp6_cepid_table, udp6_cepid_table_count);
 			if (cepid < 0)
 				return -ENOMEM;
 
-			T_UDP6_CCEP ccep = { 0, {ntohl(addr_in6->sin6_addr.__in6_union.__s6_addr), ntohs(addr_in6->sin6_port)}, (FP)socket_udp6_callback };
+			T_UDP6_CCEP ccep = { 0, { { ntohl(addr_in6->sin6_addr.__in6_union.__s6_addr) }, ntohs(addr_in6->sin6_port)}, (FP)socket_udp6_callback };
 			ret = udp6_cre_cep(cepid, &ccep);
 			if (ret != E_OK) {
-				delete_id(udp_cepid_table, udp_cepid_table_count, cepid);
+				delete_id(udp6_cepid_table, udp6_cepid_table_count, cepid);
 				return -ENOMEM;
 			}
@@ -407,5 +486,5 @@
 
 		struct sockaddr_in6 *laddr = &socket->laddr6;
-		T_TCP6_CREP crep = { 0, {ntohl(laddr->sin6_addr.__in6_union.__s6_addr), ntohs(laddr->sin6_port)} };
+		T_TCP6_CREP crep = { 0, { { ntohl(laddr->sin6_addr.__in6_union.__s6_addr) }, ntohs(laddr->sin6_port)} };
 		ret = tcp6_cre_rep(repid, &crep);
 		if (ret != E_OK) {
@@ -423,5 +502,5 @@
 }
 
-int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
+int shell_connect(int fd, const struct sockaddr *addr, socklen_t alen)
 {
 	SOCKET *fp = fd_to_fp(fd);
@@ -435,5 +514,5 @@
 	switch (socket->family) {
 	case AF_INET: {
-		if (len < 8) {
+		if (alen < sizeof(struct sockaddr_in)) {
 			return -EINVAL;
 		}
@@ -455,14 +534,17 @@
 			}
 			fp->handle = cepid;
+			fp->writable = 1;
 			socket->cepid = cepid;
 		}
 		struct sockaddr_in *laddr = &socket->laddr4;
 		struct sockaddr_in *raddr = &socket->raddr4;
-		memset(raddr, 0, sizeof(*raddr));
-		memcpy(raddr, addr, len);
+		memcpy(raddr, addr, sizeof(struct sockaddr_in));
 		T_IPV4EP lep = { ntohl(laddr->sin_addr.s_addr), ntohs(laddr->sin_port) };
 		T_IPV4EP rep = { ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port) };
 		ret = tcp_con_cep(socket->cepid, &lep, &rep, SOCKET_TIMEOUT);
-		if (ret < 0) {
+		if (ret == E_TMOUT) {
+			return -ETIMEDOUT;
+		}
+		else if (ret < 0) {
 			return -EHOSTUNREACH;
 		}
@@ -470,5 +552,5 @@
 	}
 	case AF_INET6: {
-		if (len < 20) {
+		if (alen < sizeof(struct sockaddr_in6)) {
 			return -EINVAL;
 		}
@@ -490,14 +572,21 @@
 			}
 			fp->handle = cepid;
+			fp->writable = 1;
 			socket->cepid = cepid;
 		}
 		struct sockaddr_in6 *laddr = &socket->laddr6;
 		struct sockaddr_in6 *raddr = &socket->raddr6;
-		memset(raddr, 0, sizeof(*raddr));
-		memcpy(raddr, addr, len);
-		T_IPV6EP lep = { ntohl(laddr->sin6_addr.__in6_union.__s6_addr), ntohs(laddr->sin6_port) };
-		T_IPV6EP rep = { ntohl(raddr->sin6_addr.__in6_union.__s6_addr), ntohs(raddr->sin6_port) };
+		memcpy(raddr, addr, sizeof(struct sockaddr_in6));
+		T_IPV6EP lep;
+		addrcpy(&lep.ipaddr, &laddr->sin6_addr, 16);
+		lep.portno = ntohs(laddr->sin6_port);
+		T_IPV6EP rep;
+		addrcpy(&rep.ipaddr, &raddr->sin6_addr, 16);
+		rep.portno = ntohs(raddr->sin6_port);
 		ret = tcp6_con_cep(socket->cepid, &lep, &rep, SOCKET_TIMEOUT);
-		if (ret < 0) {
+		if (ret == E_TMOUT) {
+			return -ETIMEDOUT;
+		}
+		else if (ret < 0) {
 			return -EHOSTUNREACH;
 		}
@@ -508,8 +597,10 @@
 	}
 
+	if (fp->writeevt_w != fp->writeevt_r) fp->writeevt_r++;
+
 	return 0;
 }
 
-int shell_accept(int fd, struct sockaddr *__restrict addr, socklen_t *__restrict len)
+int shell_accept(int fd, struct sockaddr *__restrict addr, socklen_t *__restrict alen)
 {
 	SOCKET *lfp = fd_to_fp(fd);
@@ -550,4 +641,5 @@
 			}
 			fp->handle = cepid;
+			fp->writable = 1;
 			socket->cepid = cepid;
 		}
@@ -555,4 +647,5 @@
 			cepid = ((socket_t *)lfp->exinf)->cepid;
 			fp->handle = cepid;
+			fp->writable = 1;
 			lfp->handle = tmax_tcp_cepid + ((socket_t *)lfp->exinf)->repid;
 			((socket_t *)lfp->exinf)->cepid = 0;
@@ -566,19 +659,19 @@
 		}
 		struct sockaddr_in *raddr = &socket->raddr4;
-		memset(raddr, 0, sizeof(*raddr));
+		memset(raddr, 0, sizeof(struct sockaddr_in));
 		raddr->sin_family = AF_INET;
 		raddr->sin_port = htons(rep.portno);
 		raddr->sin_addr.s_addr = htonl(rep.ipaddr);
 
-		if (addr != NULL && len != NULL) {
-			int sz = *len;
-			if (sz < 8) {
+		if (addr != NULL && alen != NULL) {
+			int sz = *alen;
+			if (sz < sizeof(struct sockaddr_in)) {
 				return -EINVAL;
 			}
 			struct sockaddr_in *raddr = &socket->raddr4;
-			if (sz > sizeof(*raddr))
-				sz = sizeof(*raddr);
+			if (sz > sizeof(struct sockaddr_in))
+				sz = sizeof(struct sockaddr_in);
 			memcpy(addr, raddr, sz);
-			*len = sizeof(*raddr);
+			*alen = sz;
 		}
 		break;
@@ -603,4 +696,5 @@
 			}
 			fp->handle = cepid;
+			fp->writable = 1;
 			socket->cepid = cepid;
 		}
@@ -608,4 +702,5 @@
 			cepid = ((socket_t *)lfp->exinf)->cepid;
 			fp->handle = cepid;
+			fp->writable = 1;
 			lfp->handle = tmax_tcp6_cepid + ((socket_t *)lfp->exinf)->repid;
 			((socket_t *)lfp->exinf)->cepid = 0;
@@ -613,5 +708,5 @@
 			((socket_t *)lfp->exinf)->buf = 0;
 		}
-		T_IPV6EP rep = { 0, 0 };
+		T_IPV6EP rep = { { 0 }, 0 };
 		ret = tcp6_acp_cep(socket->cepid, socket->repid, &rep, TMO_FEVR);
 		if (ret < 0) {
@@ -619,24 +714,19 @@
 		}
 		struct sockaddr_in6 *raddr = &socket->raddr6;
-		memset(raddr, 0, sizeof(*raddr));
+		memset(raddr, 0, sizeof(struct sockaddr_in6));
 		raddr->sin6_family = AF_INET;
 		raddr->sin6_port = htons(rep.portno);
-#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
-		memcpy(raddr->sin6_addr.__in6_union.__s6_addr, rep.ipaddr.__u6_addr.__u6_addr8, 16);
-#else
-		for (int i = 0; i < 16; i++)
-			raddr->sin6_addr.__in6_union.__s6_addr[i] = rep.ipaddr.__u6_addr.__u6_addr8[i];
-#endif
-
-		if (addr != NULL && len != NULL) {
-			int sz = *len;
-			if (sz < 8) {
+		addrcpy(&raddr->sin6_addr, &rep.ipaddr, 16);
+
+		if (addr != NULL && alen != NULL) {
+			int sz = *alen;
+			if (sz < sizeof(struct sockaddr_in6)) {
 				return -EINVAL;
 			}
 			struct sockaddr_in6 *raddr = &socket->raddr6;
-			if (sz > sizeof(*raddr))
-				sz = sizeof(*raddr);
+			if (sz > sizeof(struct sockaddr_in6))
+				sz = sizeof(struct sockaddr_in6);
 			memcpy(addr, raddr, sz);
-			*len = sizeof(*raddr);
+			*alen = sz;
 		}
 		break;
@@ -645,4 +735,6 @@
 		return -ENOPROTOOPT;
 	}
+
+	if (fp->writeevt_w != fp->writeevt_r) fp->writeevt_r++;
 
 	return fp->fd;
@@ -673,10 +765,9 @@
 			}
 			else {
+				int temp = len;
 				for (;;) {
 					ret = tcp_snd_dat(socket->cepid, (void *)buf, len, SOCKET_TIMEOUT);
 					if (ret < 0) {
-						if (ret == E_TMOUT)
-							return -ETIME;
-						return -ECOMM;
+						return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 					}
 					len -= ret;
@@ -685,20 +776,19 @@
 					buf = (const void *)&((uint8_t *)buf)[ret];
 				} 
+				ret = temp;
 			}
 			break;
 		}
 		case SOCK_DGRAM: {
-			int sz = alen;
-			if ((addr == NULL) || (sz < 8)) {
+			if ((addr == NULL) || (alen < sizeof(struct sockaddr_in))) {
 				return -EINVAL;
 			}
 			struct sockaddr_in *raddr = &socket->raddr4;
-			memset(raddr, 0, sizeof(*raddr));
-			memcpy(raddr, addr, sz);
+			memcpy(raddr, addr, sizeof(struct sockaddr_in));
 			T_IPV4EP rep = { ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port) };
 			ret = udp_snd_dat(socket->cepid, &rep, (void *)buf, len,
 				(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
 			if (ret < 0) {
-				return (ret == E_TMOUT) ? -ETIME : -ECOMM;
+				return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 			}
 			break;
@@ -721,10 +811,9 @@
 			}
 			else {
+				int temp = len;
 				for (;;) {
 					ret = tcp6_snd_dat(socket->cepid, (void *)buf, len, SOCKET_TIMEOUT);
 					if (ret < 0) {
-						if (ret == E_TMOUT)
-							return -ETIME;
-						return -ECOMM;
+						return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 					}
 					len -= ret;
@@ -732,21 +821,22 @@
 						break;
 					buf = (const void *)&((uint8_t *)buf)[ret];
-				} 
+				}
+				ret = temp;
 			}
 			break;
 		}
 		case SOCK_DGRAM: {
-			int sz = alen;
-			if ((addr == NULL) || (sz < 8)) {
+			if ((addr == NULL) || (alen < sizeof(struct sockaddr_in6))) {
 				return -EINVAL;
 			}
 			struct sockaddr_in6 *raddr = &socket->raddr6;
-			memset(raddr, 0, sizeof(*raddr));
-			memcpy(raddr, addr, sz);
-			T_IPV6EP rep = { ntohl(raddr->sin6_addr.__in6_union.__s6_addr), ntohs(raddr->sin6_port) };
+			memcpy(raddr, addr, sizeof(struct sockaddr_in6));
+			T_IPV6EP rep;
+			addrcpy(&rep.ipaddr, &raddr->sin6_addr, 16);
+			rep.portno = ntohs(raddr->sin6_port);
 			ret = udp6_snd_dat(socket->cepid, &rep, (void *)buf, len,
 				(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
 			if (ret < 0) {
-				return (ret == E_TMOUT) ? -ETIME : -ECOMM;
+				return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 			}
 			break;
@@ -758,4 +848,6 @@
 		return -ENOPROTOOPT;
 	}
+
+	if (fp->writeevt_w != fp->writeevt_r) fp->writeevt_r++;
 
 	return ret;
@@ -800,8 +892,10 @@
 						syslog(LOG_ERROR, "sig_sem => %d", ret);
 					}
-					ret = tcp_rcv_buf(socket->cepid, &socket->input, TMO_FEVR);
+					ret = tcp_rcv_buf(socket->cepid, &socket->input,
+						(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
 					if (ret < 0) {
-						syslog(LOG_ERROR, "tcp_rcv_buf => %d", ret);
-						return -ECOMM;
+						if ((socket->flags & O_NONBLOCK) == 0)
+							syslog(LOG_ERROR, "tcp_rcv_buf => %d", ret);
+						return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 					}
 					rsz = ret;
@@ -858,5 +952,5 @@
 					if ((socket->flags & O_NONBLOCK) == 0)
 						syslog(LOG_ERROR, "udp_rcv_buf => %d", ret);
-					return (ret == E_TMOUT) ? -ETIME : -ECOMM;
+					return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 				}
 				rsz = ret;
@@ -867,10 +961,10 @@
 					}
 					int sz = *alen;
-					memset(raddr, 0, sizeof(socket->raddr4));
+					memset(raddr, 0, sizeof(struct sockaddr_in));
 					raddr->sin_family = AF_INET;
 					raddr->sin_port = htons(rep.portno);
 					raddr->sin_addr.s_addr = htonl(rep.ipaddr);
-					if (sz > sizeof(socket->raddr4))
-						sz = sizeof(socket->raddr4);
+					if (sz > sizeof(struct sockaddr_in))
+						sz = sizeof(struct sockaddr_in);
 					memcpy(addr, raddr, sz);
 					*alen = sz;
@@ -889,6 +983,6 @@
 				if ((addr != NULL) && (alen != NULL)) {
 					int sz = *alen;
-					if (sz > sizeof(socket->raddr4))
-						sz = sizeof(socket->raddr4);
+					if (sz > sizeof(struct sockaddr_in))
+						sz = sizeof(struct sockaddr_in);
 					memcpy(addr, raddr, sz);
 					*alen = sz;
@@ -934,8 +1028,10 @@
 						syslog(LOG_ERROR, "sig_sem => %d", ret);
 					}
-					ret = tcp6_rcv_buf(socket->cepid, &socket->input, TMO_FEVR);
+					ret = tcp6_rcv_buf(socket->cepid, &socket->input,
+						(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
 					if (ret < 0) {
-						syslog(LOG_ERROR, "tcp6_rcv_buf => %d", ret);
-						return -ECOMM;
+						if ((socket->flags & O_NONBLOCK) == 0)
+							syslog(LOG_ERROR, "tcp6_rcv_buf => %d", ret);
+						return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 					}
 					rsz = ret;
@@ -986,5 +1082,5 @@
 				}
 
-				T_IPV6EP rep = { 0, 0 };
+				T_IPV6EP rep = { { 0 }, 0 };
 				ret = udp6_rcv_dat(socket->cepid, &rep, buf, len,
 					(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
@@ -992,5 +1088,5 @@
 					if ((socket->flags & O_NONBLOCK) == 0)
 						syslog(LOG_ERROR, "udp6_rcv_buf => %d", ret);
-					return (ret == E_TMOUT) ? -ETIME : -ECOMM;
+					return (ret == E_TMOUT) ? -EAGAIN : -ECOMM;
 				}
 				rsz = ret;
@@ -1001,15 +1097,10 @@
 					}
 					int sz = *alen;
-					memset(raddr, 0, sizeof(socket->raddr6));
+					memset(raddr, 0, sizeof(struct sockaddr_in6));
 					raddr->sin6_family = AF_INET;
 					raddr->sin6_port = htons(rep.portno);
-#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
-					memcpy(raddr->sin6_addr.__in6_union.__s6_addr, rep.ipaddr.__u6_addr.__u6_addr8, 16);
-#else
-					for (int i = 0; i < 16; i++)
-						raddr->sin6_addr.__in6_union.__s6_addr[i] = rep.ipaddr.__u6_addr.__u6_addr8[i];
-#endif
-					if (sz > sizeof(socket->raddr6))
-						sz = sizeof(socket->raddr6);
+					addrcpy(&raddr->sin6_addr, &rep.ipaddr, 16);
+					if (sz > sizeof(struct sockaddr_in6))
+						sz = sizeof(struct sockaddr_in6);
 					memcpy(addr, raddr, sz);
 					*alen = sz;
@@ -1028,6 +1119,6 @@
 				if ((addr != NULL) && (alen != NULL)) {
 					int sz = *alen;
-					if (sz > sizeof(socket->raddr6))
-						sz = sizeof(socket->raddr6);
+					if (sz > sizeof(struct sockaddr_in6))
+						sz = sizeof(struct sockaddr_in6);
 					memcpy(addr, raddr, sz);
 					*alen = sz;
@@ -1054,4 +1145,6 @@
 		return -ENOPROTOOPT;
 	}
+
+	if (fp->readevt_w != fp->readevt_r) fp->readevt_r++;
 
 	return ret;
@@ -1427,10 +1520,5 @@
 		struct sockaddr_in6 laddr;
 		laddr.sin6_family = AF_INET;
-#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
-		memcpy(laddr.sin6_addr.__in6_union.__s6_addr, laddr6->__u6_addr.__u6_addr8, 16);
-#else
-		for (int i = 0; i < 16; i++)
-			laddr.sin6_addr.__in6_union.__s6_addr[i] = laddr6->__u6_addr.__u6_addr8[i];
-#endif
+		addrcpy(&laddr.sin6_addr, laddr6, 16);
 		laddr.sin6_port = socket->laddr6.sin6_port;
 		*len = sizeof(struct sockaddr_in6);
@@ -1465,5 +1553,5 @@
 			delete_id(tcp_cepid_table, tcp_cepid_table_count, cepid);
 			if ((ret < 0) || (ret2 < 0)) {
-				return (ret == E_TMOUT) ? -ETIME : -EINVAL;
+				return (ret == E_TMOUT) ? -ETIMEDOUT : -EIO;
 			}
 		}
@@ -1494,5 +1582,5 @@
 			delete_id(tcp6_cepid_table, tcp6_cepid_table_count, cepid);
 			if ((ret < 0) || (ret2 < 0)) {
-				return (ret == E_TMOUT) ? -ETIME : -EINVAL;
+				return (ret == E_TMOUT) ? -ETIMEDOUT : -EIO;
 			}
 		}
@@ -1535,4 +1623,14 @@
 int tcp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg)
 {
+	socket_t *socket = (socket_t *)fp->exinf;
+
+	switch (req) {
+	case F_GETFL:
+		return socket->flags;
+	case F_SETFL:
+		socket->flags = (unsigned int)arg;
+		return 0;
+	}
+
 	return -EINVAL;
 }
@@ -1571,4 +1669,11 @@
 }
 
+bool_t tcp_fd_writable(struct SHELL_FILE *fp)
+{
+	//socket_t *socket = (socket_t *)fp->exinf;
+
+	return /*fp->writable &&*/ (fp->writeevt_w == fp->writeevt_r);
+}
+
 void tcp_fd_delete(struct SHELL_FILE *fp)
 {
@@ -1590,4 +1695,5 @@
 		return E_PAR;
 
+	socket_t *socket = (socket_t *)fp->exinf;
 	int fd = fp->fd;
 	FD_SET(fd, (fd_set *)&flgptn);
@@ -1603,5 +1709,4 @@
 			syslog(LOG_ERROR, "wai_sem => %d", ret);
 		}
-		socket_t *socket = (socket_t *)fp->exinf;
 		socket->len += len;
 		ret = sig_sem(SEM_FILEDESC);
@@ -1670,4 +1775,5 @@
 		return E_PAR;
 
+	socket_t *socket = (socket_t *)fp->exinf;
 	int fd = fp->fd;
 	FD_SET(fd, (fd_set *)&flgptn);
@@ -1683,5 +1789,4 @@
 			syslog(LOG_ERROR, "wai_sem => %d", ret);
 		}
-		socket_t *socket = (socket_t *)fp->exinf;
 		socket->len += len;
 		ret = sig_sem(SEM_FILEDESC);
@@ -1806,4 +1911,11 @@
 }
 
+bool_t udp_fd_writable(struct SHELL_FILE *fp)
+{
+	//socket_t *socket = (socket_t *)fp->exinf;
+
+	return fp->writable && (fp->writeevt_w == fp->writeevt_r);
+}
+
 void udp_fd_delete(struct SHELL_FILE *fp)
 {
@@ -1849,5 +1961,5 @@
 		socket->input = udppara->input;
 		socket->buf = GET_UDP_SDU(udppara->input, udppara->off);
-		memset(&socket->raddr4, 0, sizeof(socket->raddr4));
+		memset(&socket->raddr4, 0, sizeof(struct sockaddr_in));
 		socket->raddr4.sin_family = AF_INET;
 		socket->raddr4.sin_port = htons(udppara->rep4.portno);
@@ -1932,13 +2044,8 @@
 		socket->input = udppara->input;
 		socket->buf = GET_UDP_SDU(udppara->input, udppara->off);
-		memset(&socket->raddr6, 0, sizeof(socket->raddr6));
+		memset(&socket->raddr6, 0, sizeof(struct sockaddr_in6));
 		socket->raddr6.sin6_family = AF_INET;
 		socket->raddr6.sin6_port = htons(udppara->rep6.portno);
-#if _NET_CFG_BYTE_ORDER == _NET_CFG_BIG_ENDIAN
-		memcpy(socket->raddr6.sin6_addr.__in6_union.__s6_addr, udppara->rep6.ipaddr.__u6_addr.__u6_addr8, 16);
-#else
-		for (int i = 0; i < 16; i++)
-			socket->raddr6.sin6_addr.__in6_union.__s6_addr[i] = udppara->rep6.ipaddr.__u6_addr.__u6_addr8[i];
-#endif
+		addrcpy(&socket->raddr6.sin6_addr, &udppara->rep6.ipaddr, 16);
 		udppara->input->flags |= NB_FLG_NOREL_IFOUT;
 		ret = sig_sem(SEM_FILEDESC);
