Index: asp3_tinet_ecnl_rx/trunk/ntshell/src/socket_stub.c
===================================================================
--- asp3_tinet_ecnl_rx/trunk/ntshell/src/socket_stub.c	(revision 364)
+++ asp3_tinet_ecnl_rx/trunk/ntshell/src/socket_stub.c	(revision 374)
@@ -57,5 +57,8 @@
 #include <netinet/udp_var.h>
 #include <net/net_buf.h>
-//#include <netinet/tcp_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_var.h>
 #include <netapp/resolver.h>
 extern const ID tmax_tcp_cepid;
@@ -65,4 +68,59 @@
 
 #define SOCKET_TIMEOUT 2000000
+
+#define tcp6_cre_cep tcp_cre_cep
+#define tcp6_del_cep tcp_del_cep
+#define tcp6_del_rep tcp_del_rep
+#define tcp6_sht_cep tcp_sht_cep
+#define tcp6_cls_cep tcp_cls_cep
+#define tcp6_snd_oob tcp_snd_oob
+#define tcp6_snd_dat tcp_snd_dat
+#define tcp6_rcv_oob tcp_rcv_oob
+#define tcp6_rcv_buf tcp_rcv_buf
+#define tcp6_rel_buf tcp_rel_buf
+#define tcp6_get_opt tcp_get_opt
+#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
+
+ER	tcp6_cre_rep (ID repid, T_TCP6_CREP *pk_crep) { return E_SYS; }
+ER	tcp6_acp_cep (ID cepid, ID repid, T_IPV6EP *p_dstaddr, TMO tmout) { return E_SYS; }
+ER	tcp6_con_cep (ID cepid, T_IPV6EP *p_myaddr, T_IPV6EP *p_dstaddr, TMO tmout) { return E_SYS; }
+
+ER	udp6_cre_cep (ID cepid, T_UDP6_CCEP *pk_ccep) { 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; }
+
+const T_IN6_ADDR *in6_get_ifaddr (int_t index) { return NULL; }
+
+#endif
+
+ER socket_tcp_callback(ID cepid, FN fncd, void *p_parblk);
+ER socket_tcp6_callback(ID cepid, FN fncd, void *p_parblk);
+ER socket_udp_callback(ID cepid, FN fncd, void *p_parblk);
+ER socket_udp6_callback(ID cepid, FN fncd, void *p_parblk);
+
+static int tcp_fd_close(struct SHELL_FILE *fp);
+static size_t tcp_fd_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
+static size_t tcp_fd_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
+static off_t tcp_fd_seek(struct SHELL_FILE *fp, off_t ofs, int org);
+static int tcp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg);
+static bool_t tcp_fd_readable(struct SHELL_FILE *fp);
+static void tcp_fd_delete(struct SHELL_FILE *fp);
+
+static int udp_fd_close(struct SHELL_FILE *fp);
+static size_t udp_fd_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
+static size_t udp_fd_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
+static off_t udp_fd_seek(struct SHELL_FILE *fp, off_t ofs, int org);
+static int udp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg);
+static bool_t udp_fd_readable(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 };
 
 typedef struct id_table_t {
@@ -84,4 +142,29 @@
 #define tcp_cepid_table_count (sizeof(tcp_cepid_table) / sizeof(tcp_cepid_table[0]))
 
+#ifdef SUPPORT_INET6
+
+id_table_t tcp6_repid_table[] = {
+	{0, USR_TCP6_REP1}, {0, USR_TCP6_REP2}, {0, USR_TCP6_REP3}, {0, USR_TCP6_REP4}
+};
+#define tcp6_repid_table_count (sizeof(tcp6_repid_table) / sizeof(tcp6_repid_table[0]))
+
+id_table_t tcp6_cepid_table[] = {
+	{0, USR_TCP6_CEP1}, {0, USR_TCP6_CEP2}, {0, USR_TCP6_CEP3}, {0, USR_TCP6_CEP4},
+#ifndef TOPPERS_GRSAKURA
+	{0, USR_TCP6_CEP5}, {0, USR_TCP6_CEP6}, {0, USR_TCP6_CEP7}, {0, USR_TCP6_CEP8}
+#endif
+};
+#define tcp6_cepid_table_count (sizeof(tcp6_cepid_table) / sizeof(tcp6_cepid_table[0]))
+
+#else
+
+#define tcp6_repid_table NULL
+#define tcp6_repid_table_count 0
+
+#define tcp6_cepid_table NULL
+#define tcp6_cepid_table_count 0
+
+#endif
+
 id_table_t udp_cepid_table[] = {
 	{0, USR_UDP_CEP1}, {0, USR_UDP_CEP2}, {0, USR_UDP_CEP3}, {0, USR_UDP_CEP4}
@@ -89,4 +172,18 @@
 #define udp_cepid_table_count (sizeof(udp_cepid_table) / sizeof(udp_cepid_table[0]))
 
+#ifdef SUPPORT_INET6
+
+id_table_t udp6_cepid_table[] = {
+	{0, USR_UDP6_CEP1}, {0, USR_UDP6_CEP2}, {0, USR_UDP6_CEP3}, {0, USR_UDP6_CEP4}
+};
+#define udp6_cepid_table_count (sizeof(udp6_cepid_table) / sizeof(udp6_cepid_table[0]))
+
+#else
+
+#define udp6_cepid_table NULL
+#define udp6_cepid_table_count 0
+
+#endif
+
 ID new_id(id_table_t *table, int count)
 {
@@ -116,10 +213,5 @@
 }
 
-int delete_tcp_rep(int repid)
-{
-	return delete_tcp_fd(tmax_tcp_cepid + repid);
-}
-
-typedef struct _IO_FILE SOCKET;
+typedef struct SHELL_FILE SOCKET;
 
 int shell_socket(int family, int type, int protocol)
@@ -141,8 +233,18 @@
 	switch (type) {
 	case SOCK_STREAM:
-		fp = new_tcp_fd(0);
+		fp = new_fp(&IO_TYPE_TCP, 0, 0);
+		if (fp == NULL)
+			return -ENOMEM;
+
+		fp->exinf = malloc(sizeof(socket_t));
+		memset(fp->exinf, 0, sizeof(socket_t));
 		break;
 	case SOCK_DGRAM:
-		fp = new_udp_fd(0);
+		fp = new_fp(&IO_TYPE_UDP, 0, 1);
+		if (fp == NULL)
+			return -ENOMEM;
+
+		fp->exinf = malloc(sizeof(socket_t));
+		memset(fp->exinf, 0, sizeof(socket_t));
 		break;
 	default:
@@ -150,12 +252,9 @@
 	}
 
-	if (fp == NULL) {
-		return -ENOMEM;
-	}
-
-	fp->psock->family = family;
-	fp->psock->type = type;
-	fp->psock->protocol = protocol;
-	fp->psock->flags = flags;
+	socket_t *socket = (socket_t *)fp->exinf;
+	socket->family = family;
+	socket->type = type;
+	socket->protocol = protocol;
+	socket->flags = flags;
 
 	return fp->fd;
@@ -167,5 +266,6 @@
 	if (fp == NULL)
 		return -EBADF;
-	if (fp->psock->family != addr->sa_family)
+	socket_t *socket = (socket_t *)fp->exinf;
+	if (socket->family != addr->sa_family)
 		return -EINVAL;
 
@@ -177,6 +277,6 @@
 		}
 		struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
-		memcpy(&fp->psock->laddr4, addr, len);
-		switch (fp->psock->type) {
+		memcpy(&socket->laddr4, addr, len);
+		switch (socket->type) {
 		case SOCK_STREAM: {
 			ID cepid = new_id(tcp_cepid_table, tcp_cepid_table_count);
@@ -184,10 +284,10 @@
 				return -ENOMEM;
 
-			fp->psock->buf_size = 512 + 512;
-			fp->psock->buf = malloc(fp->psock->buf_size);
+			socket->buf_size = 512 + 512;
+			socket->buf = malloc(socket->buf_size);
 #ifdef _DEBUG
-			memset(fp->psock->buf, 0, fp->psock->buf_size);
+			memset(socket->buf, 0, socket->buf_size);
 #endif
-			T_TCP_CCEP ccep = { 0, fp->psock->buf, 512, &fp->psock->buf[512], 512, (FP)socket_tcp_callback };
+			T_TCP_CCEP ccep = { 0, socket->buf, 512, &socket->buf[512], 512, (FP)socket_tcp_callback };
 			ret = tcp_cre_cep(cepid, &ccep);
 			if (ret != E_OK) {
@@ -196,5 +296,5 @@
 			}
 			fp->handle = cepid;
-			fp->psock->cepid = cepid;
+			socket->cepid = cepid;
 			break;
 		}
@@ -211,5 +311,5 @@
 			}
 			fp->handle = cepid;
-			fp->psock->cepid = cepid;
+			socket->cepid = cepid;
 			break;
 		}
@@ -223,7 +323,49 @@
 			return -EINVAL;
 		}
-		memcpy(&fp->psock->laddr4, addr, len);
-		break;
-	}
+		struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
+		memcpy(&socket->laddr6, addr, len);
+		switch (socket->type) {
+		case SOCK_STREAM: {
+			ID cepid = new_id(tcp6_cepid_table, tcp6_cepid_table_count);
+			if (cepid < 0)
+				return -ENOMEM;
+
+			socket->buf_size = 512 + 512;
+			socket->buf = malloc(socket->buf_size);
+#ifdef _DEBUG
+			memset(socket->buf, 0, socket->buf_size);
+#endif
+			T_TCP6_CCEP ccep = { 0, socket->buf, 512, &socket->buf[512], 512, (FP)socket_tcp6_callback };
+			ret = tcp6_cre_cep(cepid, &ccep);
+			if (ret != E_OK) {
+				delete_id(tcp6_cepid_table, tcp6_cepid_table_count, cepid);
+				return -ENOMEM;
+			}
+			fp->handle = cepid;
+			socket->cepid = cepid;
+			break;
+		}
+		case SOCK_DGRAM: {
+			ID cepid = new_id(udp_cepid_table, udp_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 };
+			ret = udp6_cre_cep(cepid, &ccep);
+			if (ret != E_OK) {
+				delete_id(udp_cepid_table, udp_cepid_table_count, cepid);
+				return -ENOMEM;
+			}
+			fp->handle = cepid;
+			socket->cepid = cepid;
+			break;
+		}
+		default:
+			return -ENOPROTOOPT;
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -236,11 +378,12 @@
 	if (fp == NULL)
 		return -EBADF;
-	if (fp->psock->type != SOCK_STREAM)
+	socket_t *socket = (socket_t *)fp->exinf;
+	if (socket->type != SOCK_STREAM)
 		return -EINVAL;
 
-	fp->psock->backlog = backlog;
+	socket->backlog = backlog;
 
 	ER ret;
-	switch (fp->psock->family) {
+	switch (socket->family) {
 	case AF_INET: {
 		ID repid = new_id(tcp_repid_table, tcp_repid_table_count);
@@ -248,5 +391,5 @@
 			return -ENOMEM;
 
-		struct sockaddr_in *laddr = &fp->psock->laddr4;
+		struct sockaddr_in *laddr = &socket->laddr4;
 		T_TCP_CREP crep = { 0, {ntohl(laddr->sin_addr.s_addr), ntohs(laddr->sin_port)} };
 		ret = tcp_cre_rep(repid, &crep);
@@ -255,10 +398,24 @@
 			return -ENOMEM;
 		}
-		fp->psock->repid = repid;
+		socket->repid = repid;
 		break;
 	}
 	case AF_INET6: {
-		break;
-	}
+		ID repid = new_id(tcp6_repid_table, tcp6_repid_table_count);
+		if (repid < 0)
+			return -ENOMEM;
+
+		struct sockaddr_in6 *laddr = &socket->laddr6;
+		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) {
+			delete_id(tcp6_repid_table, tcp6_repid_table_count, repid);
+			return -ENOMEM;
+		}
+		socket->repid = repid;
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -271,24 +428,25 @@
 	if (fp == NULL)
 		return -EBADF;
-	if (fp->psock->type != SOCK_STREAM)
+	socket_t *socket = (socket_t *)fp->exinf;
+	if (socket->type != SOCK_STREAM)
 		return -EINVAL;
 
 	ER ret;
-	switch (fp->psock->family) {
+	switch (socket->family) {
 	case AF_INET: {
 		if (len < 8) {
 			return -EINVAL;
 		}
-		if (fp->psock->cepid == 0) {
+		if (socket->cepid == 0) {
 			ID cepid = new_id(tcp_cepid_table, tcp_cepid_table_count);
 			if (cepid < 0)
 				return -ENOMEM;
 
-			fp->psock->buf_size = 512 + 512;
-			fp->psock->buf = malloc(fp->psock->buf_size);
+			socket->buf_size = 512 + 512;
+			socket->buf = malloc(socket->buf_size);
 #ifdef _DEBUG
-			memset(fp->psock->buf, 0, fp->psock->buf_size);
+			memset(socket->buf, 0, socket->buf_size);
 #endif
-			T_TCP_CCEP ccep = { 0, fp->psock->buf, 512, &fp->psock->buf[512], 512, (FP)socket_tcp_callback };
+			T_TCP_CCEP ccep = { 0, socket->buf, 512, &socket->buf[512], 512, (FP)socket_tcp_callback };
 			ret = tcp_cre_cep(cepid, &ccep);
 			if (ret != E_OK) {
@@ -297,13 +455,13 @@
 			}
 			fp->handle = cepid;
-			fp->psock->cepid = cepid;
-		}
-		struct sockaddr_in *laddr = &fp->psock->laddr4;
-		struct sockaddr_in *raddr = &fp->psock->raddr4;
+			socket->cepid = cepid;
+		}
+		struct sockaddr_in *laddr = &socket->laddr4;
+		struct sockaddr_in *raddr = &socket->raddr4;
 		memset(raddr, 0, sizeof(*raddr));
 		memcpy(raddr, addr, len);
 		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(fp->psock->cepid, &lep, &rep, SOCKET_TIMEOUT);
+		ret = tcp_con_cep(socket->cepid, &lep, &rep, SOCKET_TIMEOUT);
 		if (ret < 0) {
 			return -EHOSTUNREACH;
@@ -312,6 +470,40 @@
 	}
 	case AF_INET6: {
-		break;
-	}
+		if (len < 20) {
+			return -EINVAL;
+		}
+		if (socket->cepid == 0) {
+			ID cepid = new_id(tcp6_cepid_table, tcp6_cepid_table_count);
+			if (cepid < 0)
+				return -ENOMEM;
+
+			socket->buf_size = 512 + 512;
+			socket->buf = malloc(socket->buf_size);
+#ifdef _DEBUG
+			memset(socket->buf, 0, socket->buf_size);
+#endif
+			T_TCP6_CCEP ccep = { 0, socket->buf, 512, &socket->buf[512], 512, (FP)socket_tcp6_callback };
+			ret = tcp6_cre_cep(cepid, &ccep);
+			if (ret != E_OK) {
+				delete_id(tcp6_cepid_table, tcp6_cepid_table_count, cepid);
+				return -ENOMEM;
+			}
+			fp->handle = cepid;
+			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) };
+		ret = tcp6_con_cep(socket->cepid, &lep, &rep, SOCKET_TIMEOUT);
+		if (ret < 0) {
+			return -EHOSTUNREACH;
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -324,29 +516,32 @@
 	if (lfp == NULL)
 		return -EBADF;
-	if (lfp->psock->type != SOCK_STREAM)
+	if (((socket_t *)lfp->exinf)->type != SOCK_STREAM)
 		return -EINVAL;
 
-	SOCKET *fp = new_tcp_fd(0);
-	if (fp == NULL) {
+	SOCKET *fp = new_fp(&IO_TYPE_TCP, 0, 0);
+	if (fp == NULL)
 		return -ENOMEM;
-	}
-
-	memcpy(fp->psock, lfp->psock, offsetof(socket_t, buf_size));
+
+	fp->exinf = malloc(sizeof(socket_t));
+	memset(fp->exinf, 0, sizeof(socket_t));
+
+	memcpy(fp->exinf, lfp->exinf, offsetof(socket_t, buf_size));
 
 	ER ret;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
 		ID cepid;
-		if (fp->psock->cepid == 0) {
+		if (socket->cepid == 0) {
 			cepid = new_id(tcp_cepid_table, tcp_cepid_table_count);
 			if (cepid < 0)
 				return -ENOMEM;
 
-			fp->psock->buf_size = 512 + 512;
-			fp->psock->buf = malloc(fp->psock->buf_size);
+			socket->buf_size = 512 + 512;
+			socket->buf = malloc(socket->buf_size);
 #ifdef _DEBUG
-			memset(fp->psock->buf, 0, fp->psock->buf_size);
+			memset(socket->buf, 0, socket->buf_size);
 #endif
-			T_TCP_CCEP ccep = { 0, fp->psock->buf, 512, &fp->psock->buf[512], 512, (FP)socket_tcp_callback };
+			T_TCP_CCEP ccep = { 0, socket->buf, 512, &socket->buf[512], 512, (FP)socket_tcp_callback };
 			ret = tcp_cre_cep(cepid, &ccep);
 			if (ret != E_OK) {
@@ -355,41 +550,98 @@
 			}
 			fp->handle = cepid;
-			fp->psock->cepid = cepid;
+			socket->cepid = cepid;
 		}
 		else {
-			cepid = lfp->psock->cepid;
+			cepid = ((socket_t *)lfp->exinf)->cepid;
 			fp->handle = cepid;
-			lfp->handle = tmax_tcp_cepid + lfp->psock->repid;
-			lfp->psock->cepid = 0;
-			lfp->psock->buf_size = 0;
-			lfp->psock->buf = 0;
+			lfp->handle = tmax_tcp_cepid + ((socket_t *)lfp->exinf)->repid;
+			((socket_t *)lfp->exinf)->cepid = 0;
+			((socket_t *)lfp->exinf)->buf_size = 0;
+			((socket_t *)lfp->exinf)->buf = 0;
 		}
 		T_IPV4EP rep = { 0, 0 };
-		ret = tcp_acp_cep(fp->psock->cepid, fp->psock->repid, &rep, TMO_FEVR);
+		ret = tcp_acp_cep(socket->cepid, socket->repid, &rep, TMO_FEVR);
 		if (ret < 0) {
 			return -ENOMEM;
 		}
-		struct sockaddr_in *raddr = &fp->psock->raddr4;
+		struct sockaddr_in *raddr = &socket->raddr4;
 		memset(raddr, 0, sizeof(*raddr));
 		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) {
+				return -EINVAL;
+			}
+			struct sockaddr_in *raddr = &socket->raddr4;
+			if (sz > sizeof(*raddr))
+				sz = sizeof(*raddr);
+			memcpy(addr, raddr, sz);
+			*len = sizeof(*raddr);
+		}
 		break;
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
-	}
-
-	if (addr != NULL && len != NULL) {
-		int sz = *len;
-		if (sz < 8) {
-			return -EINVAL;
-		}
-		struct sockaddr_in *raddr = &fp->psock->raddr4;
-		if (sz > sizeof(*raddr))
-			sz = sizeof(*raddr);
-		memcpy(addr, raddr, sz);
-		*len = sizeof(*raddr);
+		ID cepid;
+		if (socket->cepid == 0) {
+			cepid = new_id(tcp6_cepid_table, tcp6_cepid_table_count);
+			if (cepid < 0)
+				return -ENOMEM;
+
+			socket->buf_size = 512 + 512;
+			socket->buf = malloc(socket->buf_size);
+#ifdef _DEBUG
+			memset(socket->buf, 0, socket->buf_size);
+#endif
+			T_TCP6_CCEP ccep = { 0, socket->buf, 512, &socket->buf[512], 512, (FP)socket_tcp6_callback };
+			ret = tcp6_cre_cep(cepid, &ccep);
+			if (ret != E_OK) {
+				delete_id(tcp6_cepid_table, tcp6_cepid_table_count, cepid);
+				return -ENOMEM;
+			}
+			fp->handle = cepid;
+			socket->cepid = cepid;
+		}
+		else {
+			cepid = ((socket_t *)lfp->exinf)->cepid;
+			fp->handle = cepid;
+			lfp->handle = tmax_tcp6_cepid + ((socket_t *)lfp->exinf)->repid;
+			((socket_t *)lfp->exinf)->cepid = 0;
+			((socket_t *)lfp->exinf)->buf_size = 0;
+			((socket_t *)lfp->exinf)->buf = 0;
+		}
+		T_IPV6EP rep = { 0, 0 };
+		ret = tcp6_acp_cep(socket->cepid, socket->repid, &rep, TMO_FEVR);
+		if (ret < 0) {
+			return -ENOMEM;
+		}
+		struct sockaddr_in6 *raddr = &socket->raddr6;
+		memset(raddr, 0, sizeof(*raddr));
+		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) {
+				return -EINVAL;
+			}
+			struct sockaddr_in6 *raddr = &socket->raddr6;
+			if (sz > sizeof(*raddr))
+				sz = sizeof(*raddr);
+			memcpy(addr, raddr, sz);
+			*len = sizeof(*raddr);
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -405,7 +657,8 @@
 
 	int ret = 0;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		switch (fp->psock->type) {
+		switch (socket->type) {
 		case SOCK_STREAM: {
 			if ((addr != NULL) || (alen != 0)) {
@@ -414,5 +667,5 @@
 
 			if (flags & MSG_OOB) {
-				ret = tcp_snd_oob(fp->psock->cepid, (void *)buf, len, SOCKET_TIMEOUT);
+				ret = tcp_snd_oob(socket->cepid, (void *)buf, len, SOCKET_TIMEOUT);
 				if (ret < 0) {
 					return -ECOMM;
@@ -421,5 +674,5 @@
 			else {
 				for (;;) {
-					ret = tcp_snd_dat(fp->psock->cepid, (void *)buf, len, SOCKET_TIMEOUT);
+					ret = tcp_snd_dat(socket->cepid, (void *)buf, len, SOCKET_TIMEOUT);
 					if (ret < 0) {
 						if (ret == E_TMOUT)
@@ -440,10 +693,10 @@
 				return -EINVAL;
 			}
-			struct sockaddr_in *raddr = &fp->psock->raddr4;
+			struct sockaddr_in *raddr = &socket->raddr4;
 			memset(raddr, 0, sizeof(*raddr));
 			memcpy(raddr, addr, sz);
 			T_IPV4EP rep = { ntohl(raddr->sin_addr.s_addr), ntohs(raddr->sin_port) };
-			ret = udp_snd_dat(fp->psock->cepid, &rep, (void *)buf, len,
-				(fp->psock->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
+			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;
@@ -455,6 +708,53 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		switch (socket->type) {
+		case SOCK_STREAM: {
+			if ((addr != NULL) || (alen != 0)) {
+				return -EISCONN;
+			}
+
+			if (flags & MSG_OOB) {
+				ret = tcp6_snd_oob(socket->cepid, (void *)buf, len, SOCKET_TIMEOUT);
+				if (ret < 0) {
+					return -ECOMM;
+				}
+			}
+			else {
+				for (;;) {
+					ret = tcp6_snd_dat(socket->cepid, (void *)buf, len, SOCKET_TIMEOUT);
+					if (ret < 0) {
+						if (ret == E_TMOUT)
+							return -ETIME;
+						return -ECOMM;
+					}
+					len -= ret;
+					if (len <= 0)
+						break;
+					buf = (const void *)&((uint8_t *)buf)[ret];
+				} 
+			}
+			break;
+		}
+		case SOCK_DGRAM: {
+			int sz = alen;
+			if ((addr == NULL) || (sz < 8)) {
+				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) };
+			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;
+			}
+			break;
+		}
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -476,10 +776,11 @@
 
 	int ret = 0;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		switch (fp->psock->type) {
+		switch (socket->type) {
 		case SOCK_STREAM: {
 			if (flags & MSG_OOB) {
-				ret = tcp_rcv_oob(fp->psock->cepid, buf, len);
+				ret = tcp_rcv_oob(socket->cepid, buf, len);
 				if (ret < 0) {
 					syslog(LOG_ERROR, "tcp_rcv_oob => %d", ret);
@@ -489,15 +790,15 @@
 			else {
 				int rsz, tmp;
-				if (fp->psock->input == NULL) {
+				if (socket->input == NULL) {
 					ret = wai_sem(SEM_FILEDESC);
 					if (ret < 0) {
 						syslog(LOG_ERROR, "wai_sem => %d", ret);
 					}
-					fp->psock->len = 0;
+					socket->len = 0;
 					ret = sig_sem(SEM_FILEDESC);
 					if (ret < 0) {
 						syslog(LOG_ERROR, "sig_sem => %d", ret);
 					}
-					ret = tcp_rcv_buf(fp->psock->cepid, &fp->psock->input, TMO_FEVR);
+					ret = tcp_rcv_buf(socket->cepid, &socket->input, TMO_FEVR);
 					if (ret < 0) {
 						syslog(LOG_ERROR, "tcp_rcv_buf => %d", ret);
@@ -507,15 +808,15 @@
 				}
 				else
-					rsz = fp->psock->len;
+					rsz = socket->len;
 				tmp = rsz;
 				if (rsz > len)
 					rsz = len;
 				if (rsz >= 0) {
-					memcpy(buf, fp->psock->input, rsz);
+					memcpy(buf, socket->input, rsz);
 					ret = wai_sem(SEM_FILEDESC);
 					if (ret < 0) {
 						syslog(LOG_ERROR, "wai_sem => %d", ret);
 					}
-					fp->psock->len = tmp - rsz;
+					socket->len = tmp - rsz;
 					ret = sig_sem(SEM_FILEDESC);
 					if (ret < 0) {
@@ -523,9 +824,9 @@
 					}
 					if (tmp - rsz == 0) {
-						fp->psock->input = NULL;
+						socket->input = NULL;
 					}
 					else
-						fp->psock->input = (void *)&((uint8_t *)fp->psock->input)[rsz];
-					ret = tcp_rel_buf(fp->psock->cepid, rsz);
+						socket->input = (void *)&((uint8_t *)socket->input)[rsz];
+					ret = tcp_rel_buf(socket->cepid, rsz);
 					if ((ret != E_OBJ) && (ret < 0)) {
 						syslog(LOG_ERROR, "tcp_rel_buf => %d", ret);
@@ -538,5 +839,5 @@
 		}
 		case SOCK_DGRAM: {
-			struct sockaddr_in *raddr = &fp->psock->raddr4;
+			struct sockaddr_in *raddr = &socket->raddr4;
 			int rsz;
 			ret = wai_sem(SEM_FILEDESC);
@@ -544,5 +845,5 @@
 				syslog(LOG_ERROR, "wai_sem => %d", ret);
 			}
-			T_NET_BUF *input = fp->psock->input;
+			T_NET_BUF *input = socket->input;
 			if (input == NULL) {
 				ret = sig_sem(SEM_FILEDESC);
@@ -552,8 +853,9 @@
 
 				T_IPV4EP rep = { 0, 0 };
-				ret = udp_rcv_dat(fp->psock->cepid, &rep, buf, len,
-					(fp->psock->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
+				ret = udp_rcv_dat(socket->cepid, &rep, buf, len,
+					(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
 				if (ret < 0) {
-					syslog(LOG_ERROR, "udp_rcv_buf => %d", ret);
+					if ((socket->flags & O_NONBLOCK) == 0)
+						syslog(LOG_ERROR, "udp_rcv_buf => %d", ret);
 					return (ret == E_TMOUT) ? -ETIME : -ECOMM;
 				}
@@ -565,10 +867,10 @@
 					}
 					int sz = *alen;
-					memset(raddr, 0, sizeof(fp->psock->raddr4));
+					memset(raddr, 0, sizeof(socket->raddr4));
 					raddr->sin_family = AF_INET;
 					raddr->sin_port = htons(rep.portno);
 					raddr->sin_addr.s_addr = htonl(rep.ipaddr);
-					if (sz > sizeof(fp->psock->raddr4))
-						sz = sizeof(fp->psock->raddr4);
+					if (sz > sizeof(socket->raddr4))
+						sz = sizeof(socket->raddr4);
 					memcpy(addr, raddr, sz);
 					*alen = sz;
@@ -580,13 +882,13 @@
 			}
 			else {
-				rsz = fp->psock->len;
-				void *pbuf = fp->psock->buf;
-				fp->psock->input = NULL;
-				fp->psock->len = 0;
-				fp->psock->buf = NULL;
+				rsz = socket->len;
+				void *pbuf = socket->buf;
+				socket->input = NULL;
+				socket->len = 0;
+				socket->buf = NULL;
 				if ((addr != NULL) && (alen != NULL)) {
 					int sz = *alen;
-					if (sz > sizeof(fp->psock->raddr4))
-						sz = sizeof(fp->psock->raddr4);
+					if (sz > sizeof(socket->raddr4))
+						sz = sizeof(socket->raddr4);
 					memcpy(addr, raddr, sz);
 					*alen = sz;
@@ -611,6 +913,144 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		switch (socket->type) {
+		case SOCK_STREAM: {
+			if (flags & MSG_OOB) {
+				ret = tcp6_rcv_oob(socket->cepid, buf, len);
+				if (ret < 0) {
+					syslog(LOG_ERROR, "tcp6_rcv_oob => %d", ret);
+					return -ECOMM;
+				}
+			}
+			else {
+				int rsz, tmp;
+				if (socket->input == NULL) {
+					ret = wai_sem(SEM_FILEDESC);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "wai_sem => %d", ret);
+					}
+					socket->len = 0;
+					ret = sig_sem(SEM_FILEDESC);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "sig_sem => %d", ret);
+					}
+					ret = tcp6_rcv_buf(socket->cepid, &socket->input, TMO_FEVR);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "tcp6_rcv_buf => %d", ret);
+						return -ECOMM;
+					}
+					rsz = ret;
+				}
+				else
+					rsz = socket->len;
+				tmp = rsz;
+				if (rsz > len)
+					rsz = len;
+				if (rsz >= 0) {
+					memcpy(buf, socket->input, rsz);
+					ret = wai_sem(SEM_FILEDESC);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "wai_sem => %d", ret);
+					}
+					socket->len = tmp - rsz;
+					ret = sig_sem(SEM_FILEDESC);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "sig_sem => %d", ret);
+					}
+					if (tmp - rsz == 0) {
+						socket->input = NULL;
+					}
+					else
+						socket->input = (void *)&((uint8_t *)socket->input)[rsz];
+					ret = tcp6_rel_buf(socket->cepid, rsz);
+					if ((ret != E_OBJ) && (ret < 0)) {
+						syslog(LOG_ERROR, "tcp6_rel_buf => %d", ret);
+						//return -ECOMM;
+					}
+				}
+				ret = rsz;
+			}
+			break;
+		}
+		case SOCK_DGRAM: {
+			struct sockaddr_in6 *raddr = &socket->raddr6;
+			int rsz;
+			ret = wai_sem(SEM_FILEDESC);
+			if (ret < 0) {
+				syslog(LOG_ERROR, "wai_sem => %d", ret);
+			}
+			T_NET_BUF *input = socket->input;
+			if (input == NULL) {
+				ret = sig_sem(SEM_FILEDESC);
+				if (ret < 0) {
+					syslog(LOG_ERROR, "sig_sem => %d", ret);
+				}
+
+				T_IPV6EP rep = { 0, 0 };
+				ret = udp6_rcv_dat(socket->cepid, &rep, buf, len,
+					(socket->flags & O_NONBLOCK) ? TMO_POL : SOCKET_TIMEOUT);
+				if (ret < 0) {
+					if ((socket->flags & O_NONBLOCK) == 0)
+						syslog(LOG_ERROR, "udp6_rcv_buf => %d", ret);
+					return (ret == E_TMOUT) ? -ETIME : -ECOMM;
+				}
+				rsz = ret;
+				if ((addr != NULL) && (alen != NULL)) {
+					ret = wai_sem(SEM_FILEDESC);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "wai_sem => %d", ret);
+					}
+					int sz = *alen;
+					memset(raddr, 0, sizeof(socket->raddr6));
+					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);
+					memcpy(addr, raddr, sz);
+					*alen = sz;
+					ret = sig_sem(SEM_FILEDESC);
+					if (ret < 0) {
+						syslog(LOG_ERROR, "sig_sem => %d", ret);
+					}
+				}
+			}
+			else {
+				rsz = socket->len;
+				void *pbuf = socket->buf;
+				socket->input = NULL;
+				socket->len = 0;
+				socket->buf = NULL;
+				if ((addr != NULL) && (alen != NULL)) {
+					int sz = *alen;
+					if (sz > sizeof(socket->raddr6))
+						sz = sizeof(socket->raddr6);
+					memcpy(addr, raddr, sz);
+					*alen = sz;
+				}
+				ret = sig_sem(SEM_FILEDESC);
+				if (ret < 0) {
+					syslog(LOG_ERROR, "sig_sem => %d", ret);
+				}
+				if (rsz > len)
+					rsz = len;
+				memcpy(buf, pbuf, rsz);
+				ret = rel_net_buf(input);
+				if (ret < 0) {
+					syslog(LOG_ERROR, "rel_net_buf => %d", ret);
+					//return -ECOMM;
+				}
+			}
+			ret = rsz;
+		}
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -632,9 +1072,10 @@
 
 	ER ret;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		switch (fp->psock->type) {
+		switch (socket->type) {
 		case SOCK_STREAM: {
-			ret = tcp_sht_cep(fp->psock->cepid);
+			ret = tcp_sht_cep(socket->cepid);
 			if (ret < 0) {
 				return -ECOMM;
@@ -646,6 +1087,17 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		switch (socket->type) {
+		case SOCK_STREAM: {
+			ret = tcp6_sht_cep(socket->cepid);
+			if (ret < 0) {
+				return -ECOMM;
+			}
+			break;
+		}
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -661,7 +1113,8 @@
 
 	ER ret;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		switch (fp->psock->type) {
+		switch (socket->type) {
 		case SOCK_STREAM: {
 			switch (level) {
@@ -669,5 +1122,5 @@
 				switch (optname) {
 				case SO_REUSEADDR:
-					if (fp->psock->flags & SO_REUSEADDR) {
+					if (socket->flags & SO_REUSEADDR) {
 						*(bool *)optval = true;
 					}
@@ -677,5 +1130,5 @@
 					break;
 				case SO_KEEPALIVE:
-					if (fp->psock->flags & SO_KEEPALIVE) {
+					if (socket->flags & SO_KEEPALIVE) {
 						*(bool *)optval = true;
 					}
@@ -692,5 +1145,5 @@
 				break;
 			case IPPROTO_TCP:
-				ret = tcp_get_opt(fp->psock->cepid, optname, (void *)optval, *optlen);
+				ret = tcp_get_opt(socket->cepid, optname, (void *)optval, *optlen);
 				if (ret < 0) {
 					return -EINVAL;
@@ -706,5 +1159,5 @@
 			switch (level) {
 			case IPPROTO_UDP:
-				ret = udp_get_opt(fp->psock->cepid, optname, (void *)optval, *optlen);
+				ret = udp_get_opt(socket->cepid, optname, (void *)optval, *optlen);
 				if (ret < 0) {
 					return -EINVAL;
@@ -721,6 +1174,63 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		switch (socket->type) {
+		case SOCK_STREAM: {
+			switch (level) {
+			case SOL_SOCKET:
+				switch (optname) {
+				case SO_REUSEADDR:
+					if (socket->flags & SO_REUSEADDR) {
+						*(bool *)optval = true;
+					}
+					else {
+						*(bool *)optval = false;
+					}
+					break;
+				case SO_KEEPALIVE:
+					if (socket->flags & SO_KEEPALIVE) {
+						*(bool *)optval = true;
+					}
+					else {
+						*(bool *)optval = false;
+					}
+					break;
+				case SO_ERROR:
+					*(int *)optval = 0;
+					break;
+				default:
+					return -EINVAL;
+				}
+				break;
+			case IPPROTO_TCP:
+				ret = tcp6_get_opt(socket->cepid, optname, (void *)optval, *optlen);
+				if (ret < 0) {
+					return -EINVAL;
+				}
+				*optlen = ret;
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		}
+		case SOCK_DGRAM: {
+			switch (level) {
+			case IPPROTO_UDP:
+				ret = udp6_get_opt(socket->cepid, optname, (void *)optval, *optlen);
+				if (ret < 0) {
+					return -EINVAL;
+				}
+				*optlen = ret;
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		}
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -736,7 +1246,8 @@
 
 	ER ret;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		switch (fp->psock->type) {
+		switch (socket->type) {
 		case SOCK_STREAM: {
 			switch (level){
@@ -745,16 +1256,16 @@
 				case SO_REUSEADDR:
 					if (*(bool *)optval) {
-						fp->psock->flags |= SO_REUSEADDR;
+						socket->flags |= SO_REUSEADDR;
 					}
 					else {
-						fp->psock->flags &= ~SO_REUSEADDR;
+						socket->flags &= ~SO_REUSEADDR;
 					}
 					break;
 				case SO_KEEPALIVE:
 					if (*(bool *)optval) {
-						fp->psock->flags |= SO_KEEPALIVE;
+						socket->flags |= SO_KEEPALIVE;
 					}
 					else {
-						fp->psock->flags &= ~SO_KEEPALIVE;
+						socket->flags &= ~SO_KEEPALIVE;
 					}
 					break;
@@ -764,5 +1275,5 @@
 				break;
 			case IPPROTO_TCP:
-				ret = tcp_set_opt(fp->psock->cepid, optname, (void *)optval, optlen);
+				ret = tcp_set_opt(socket->cepid, optname, (void *)optval, optlen);
 				if (ret < 0) {
 					return -EINVAL;
@@ -777,5 +1288,5 @@
 			switch (level){
 			case IPPROTO_UDP:
-				ret = udp_set_opt(fp->psock->cepid, optname, (void *)optval, optlen);
+				ret = udp_set_opt(socket->cepid, optname, (void *)optval, optlen);
 				if (ret < 0) {
 					return -EINVAL;
@@ -791,6 +1302,58 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		switch (socket->type) {
+		case SOCK_STREAM: {
+			switch (level){
+			case SOL_SOCKET:
+				switch (optname) {
+				case SO_REUSEADDR:
+					if (*(bool *)optval) {
+						socket->flags |= SO_REUSEADDR;
+					}
+					else {
+						socket->flags &= ~SO_REUSEADDR;
+					}
+					break;
+				case SO_KEEPALIVE:
+					if (*(bool *)optval) {
+						socket->flags |= SO_KEEPALIVE;
+					}
+					else {
+						socket->flags &= ~SO_KEEPALIVE;
+					}
+					break;
+				default:
+					return -EINVAL;
+				}
+				break;
+			case IPPROTO_TCP:
+				ret = tcp6_set_opt(socket->cepid, optname, (void *)optval, optlen);
+				if (ret < 0) {
+					return -EINVAL;
+				}
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		}
+		case SOCK_DGRAM: {
+			switch (level){
+			case IPPROTO_UDP:
+				ret = udp6_set_opt(socket->cepid, optname, (void *)optval, optlen);
+				if (ret < 0) {
+					return -EINVAL;
+				}
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		}
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -809,7 +1372,8 @@
 
 	socklen_t size = *len;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		struct sockaddr_in *raddr = &fp->psock->raddr4;
+		struct sockaddr_in *raddr = &socket->raddr4;
 		*len = sizeof(struct sockaddr_in);
 		if (size > sizeof(struct sockaddr_in))
@@ -819,6 +1383,13 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		struct sockaddr_in6 *raddr = &socket->raddr6;
+		*len = sizeof(struct sockaddr_in6);
+		if (size > sizeof(struct sockaddr_in6))
+			size = sizeof(struct sockaddr_in6);
+		memcpy(addr, raddr, size);
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -837,5 +1408,6 @@
 
 	socklen_t size = *len;
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
 		const T_IN4_ADDR *laddr4 = in4_get_ifaddr(0);
@@ -843,5 +1415,5 @@
 		laddr.sin_family = AF_INET;
 		laddr.sin_addr.s_addr = htonl(*laddr4);
-		laddr.sin_port = fp->psock->laddr4.sin_port;
+		laddr.sin_port = socket->laddr4.sin_port;
 		memset(&laddr.sin_zero, 0, sizeof(laddr.sin_zero));
 		*len = sizeof(struct sockaddr_in);
@@ -852,6 +1424,22 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		const T_IN6_ADDR *laddr6 = in6_get_ifaddr(0);
+		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
+		laddr.sin6_port = socket->laddr6.sin6_port;
+		*len = sizeof(struct sockaddr_in6);
+		if (size > sizeof(struct sockaddr_in6))
+			size = sizeof(struct sockaddr_in6);
+		memcpy(addr, &laddr, size);
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -859,21 +1447,20 @@
 }
 
-int tcp_fd_close(struct _IO_FILE *fp)
+int tcp_fd_close(struct SHELL_FILE *fp)
 {
 	ER ret, ret2;
 
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		if (fp->psock->cepid != 0) {
-			ID cepid = fp->psock->cepid;
+		if (socket->cepid != 0) {
+			ID cepid = socket->cepid;
 			ret = tcp_sht_cep(cepid);
 			if (ret < 0) {
 				//return -1;
 			}
-			ret = tcp_cls_cep(cepid, (fp->psock->repid != 0) ? 0 : SOCKET_TIMEOUT);
+			ret = tcp_cls_cep(cepid, (socket->repid != 0) ? 0 : SOCKET_TIMEOUT);
 			ret2 = tcp_del_cep(cepid);
-			free(fp->psock->buf);
-			fp->psock->buf = NULL;
-			delete_tcp_fd(cepid);
+			//delete_fd_by_id(&IO_TYPE_TCP, cepid);
 			delete_id(tcp_cepid_table, tcp_cepid_table_count, cepid);
 			if ((ret < 0) || (ret2 < 0)) {
@@ -881,10 +1468,8 @@
 			}
 		}
-		else if (fp->psock->repid != 0) {
-			ID repid = fp->psock->repid;
+		else if (socket->repid != 0) {
+			ID repid = socket->repid;
 			ret = tcp_del_rep(repid);
-			free(fp->psock->buf);
-			fp->psock->buf = NULL;
-			delete_tcp_fd(tmax_tcp_cepid + repid);
+			//delete_fd_by_id(&IO_TYPE_TCP, tmax_tcp_cepid + repid);
 			delete_id(tcp_repid_table, tcp_repid_table_count, repid);
 			if (ret < 0) {
@@ -893,6 +1478,4 @@
 		}
 		else {
-			free(fp->psock->buf);
-			fp->psock->buf = NULL;
 			return -EINVAL;
 		}
@@ -900,6 +1483,34 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		if (socket->cepid != 0) {
+			ID cepid = socket->cepid;
+			ret = tcp6_sht_cep(cepid);
+			if (ret < 0) {
+				//return -1;
+			}
+			ret = tcp6_cls_cep(cepid, (socket->repid != 0) ? 0 : SOCKET_TIMEOUT);
+			ret2 = tcp6_del_cep(cepid);
+			//delete_fd_by_id(&IO_TYPE_TCP, cepid);
+			delete_id(tcp6_cepid_table, tcp6_cepid_table_count, cepid);
+			if ((ret < 0) || (ret2 < 0)) {
+				return (ret == E_TMOUT) ? -ETIME : -EINVAL;
+			}
+		}
+		else if (socket->repid != 0) {
+			ID repid = socket->repid;
+			ret = tcp6_del_rep(repid);
+			//delete_fd_by_id(&IO_TYPE_TCP, tmax_tcp6_cepid + repid);
+			delete_id(tcp6_repid_table, tcp6_repid_table_count, repid);
+			if (ret < 0) {
+				return -EINVAL;
+			}
+		}
+		else {
+			return -EINVAL;
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -907,36 +1518,237 @@
 }
 
-size_t tcp_fd_read(struct _IO_FILE *fp, unsigned char *dst, size_t dstsz)
+size_t tcp_fd_read(struct SHELL_FILE *fp, unsigned char *dst, size_t dstsz)
 {
 	return shell_recvfrom(fp->fd, dst, dstsz, 0, NULL, NULL);
 }
 
-size_t tcp_fd_write(struct _IO_FILE *fp, const unsigned char *src, size_t srcsz)
+size_t tcp_fd_write(struct SHELL_FILE *fp, const unsigned char *src, size_t srcsz)
 {
 	return shell_sendto(fp->fd, src, srcsz, 0, NULL, 0);
 }
 
-off_t tcp_fd_seek(struct _IO_FILE *fp, off_t ofs, int org)
+off_t tcp_fd_seek(struct SHELL_FILE *fp, off_t ofs, int org)
 {
 	return -EPERM;
 }
 
-int tcp_fd_ioctl(struct _IO_FILE *fp, int req, void *arg)
+int tcp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg)
 {
 	return -EINVAL;
 }
 
-int udp_fd_close(struct _IO_FILE *fp)
+bool_t tcp_fd_readable(struct SHELL_FILE *fp)
+{
+	ER ret;
+
+	socket_t *socket = (socket_t *)fp->exinf;
+	if (socket->cepid != 0) {
+		if (socket->len == 0) {
+			ret = tcp_rcv_buf(socket->cepid, &socket->input, TMO_NBLK);
+			if ((ret != E_WBLK) && (ret != E_OBJ) && (ret < 0)) {
+				syslog(LOG_ERROR, "tcp_rcv_buf => %d", ret);
+				//return ret;
+			}
+			if (ret > 0) {
+				ret = wai_sem(SEM_FILEDESC);
+				if (ret < 0) {
+					syslog(LOG_ERROR, "wai_sem => %d", ret);
+				}
+				socket->len += ret;
+				ret = sig_sem(SEM_FILEDESC);
+				if (ret < 0) {
+					syslog(LOG_ERROR, "sig_sem => %d", ret);
+				}
+			}
+		}
+		else ret = 1;
+		if (ret > 0) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void tcp_fd_delete(struct SHELL_FILE *fp)
+{
+	socket_t *socket = (socket_t *)fp->exinf;
+	free(socket->buf);
+	socket->buf = NULL;
+	free(fp->exinf);
+	fp->exinf = NULL;
+}
+
+ER socket_tcp_callback(ID cepid, FN fncd, void *p_parblk)
+{
+	struct SHELL_FILE *fp = id_to_fd(&IO_TYPE_TCP, cepid);
+	FLGPTN flgptn = 0;
+	ER ret;
+	int len;
+
+	if (fp == NULL)
+		return E_PAR;
+
+	int fd = fp->fd;
+	FD_SET(fd, (fd_set *)&flgptn);
+
+	switch (fncd) {
+	case TFN_TCP_RCV_BUF:
+		len = *(int *)p_parblk;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		ret = wai_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "wai_sem => %d", ret);
+		}
+		socket_t *socket = (socket_t *)fp->exinf;
+		socket->len += len;
+		ret = sig_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "sig_sem => %d", ret);
+		}
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_RCV_DAT:
+		len = *(int *)p_parblk;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		ret = wai_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "wai_sem => %d", ret);
+		}
+		socket->len += len;
+		ret = sig_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "sig_sem => %d", ret);
+		}
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_SND_DAT:
+		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_CAN_CEP:
+		if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_DEL_REP:
+		delete_fd_by_id(&IO_TYPE_TCP, tmax_tcp_cepid + cepid);
+		return E_OK;
+
+	case TFN_TCP_DEL_CEP:
+		delete_fd_by_id(&IO_TYPE_TCP, cepid);
+		return E_OK;
+
+	default:
+		return E_OK;
+	}
+}
+
+ER socket_tcp6_callback(ID cepid, FN fncd, void *p_parblk)
+{
+	struct SHELL_FILE *fp = id_to_fd(&IO_TYPE_TCP, cepid);
+	FLGPTN flgptn = 0;
+	ER ret;
+	int len;
+
+	if (fp == NULL)
+		return E_PAR;
+
+	int fd = fp->fd;
+	FD_SET(fd, (fd_set *)&flgptn);
+
+	switch (fncd) {
+	case TFN_TCP_RCV_BUF:
+		len = *(int *)p_parblk;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		ret = wai_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "wai_sem => %d", ret);
+		}
+		socket_t *socket = (socket_t *)fp->exinf;
+		socket->len += len;
+		ret = sig_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "sig_sem => %d", ret);
+		}
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_RCV_DAT:
+		len = *(int *)p_parblk;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		ret = wai_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "wai_sem => %d", ret);
+		}
+		socket->len += len;
+		ret = sig_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "sig_sem => %d", ret);
+		}
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_SND_DAT:
+		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_CAN_CEP:
+		if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_TCP_DEL_REP:
+		delete_fd_by_id(&IO_TYPE_TCP, tmax_tcp_cepid + cepid);
+		return E_OK;
+
+	case TFN_TCP_DEL_CEP:
+		delete_fd_by_id(&IO_TYPE_TCP, cepid);
+		return E_OK;
+
+	default:
+		return E_OK;
+	}
+}
+
+int udp_fd_close(struct SHELL_FILE *fp)
 {
 	ER ret;
 	ID cepid;
 
-	switch (fp->psock->family) {
+	socket_t *socket = (socket_t *)fp->exinf;
+	switch (socket->family) {
 	case AF_INET: {
-		cepid = fp->psock->cepid;
+		cepid = socket->cepid;
 		ret = udp_del_cep(cepid);
-		//free(fp->psock->buf);
-		//fp->psock->buf = NULL;
-		delete_udp_fd(cepid);
+		//delete_fd_by_id(&IO_TYPE_UDP, cepid);
 		delete_id(udp_cepid_table, udp_cepid_table_count, cepid);
 		if (ret < 0) {
@@ -946,6 +1758,15 @@
 	}
 	case AF_INET6: {
-		return -EAFNOSUPPORT;
-	}
+		cepid = socket->cepid;
+		ret = udp6_del_cep(cepid);
+		//delete_fd_by_id(&IO_TYPE_UDP, cepid);
+		delete_id(udp6_cepid_table, udp6_cepid_table_count, cepid);
+		if (ret < 0) {
+			return -EINVAL;
+		}
+		break;
+	}
+	default:
+		return -ENOPROTOOPT;
 	}
 
@@ -953,22 +1774,214 @@
 }
 
-size_t udp_fd_read(struct _IO_FILE *fp, unsigned char *dst, size_t dstsz)
+size_t udp_fd_read(struct SHELL_FILE *fp, unsigned char *dst, size_t dstsz)
 {
 	return shell_recvfrom(fp->fd, dst, dstsz, 0, NULL, NULL);
 }
 
-size_t udp_fd_write(struct _IO_FILE *fp, const unsigned char *src, size_t srcsz)
+size_t udp_fd_write(struct SHELL_FILE *fp, const unsigned char *src, size_t srcsz)
 {
 	return shell_sendto(fp->fd, src, srcsz, 0, NULL, 0);
 }
 
-off_t udp_fd_seek(struct _IO_FILE *fp, off_t ofs, int org)
+off_t udp_fd_seek(struct SHELL_FILE *fp, off_t ofs, int org)
 {
 	return -EPERM;
 }
 
-int udp_fd_ioctl(struct _IO_FILE *fp, int req, void *arg)
+int udp_fd_ioctl(struct SHELL_FILE *fp, int req, void *arg)
 {
 	return -EINVAL;
+}
+
+bool_t udp_fd_readable(struct SHELL_FILE *fp)
+{
+	socket_t *socket = (socket_t *)fp->exinf;
+	if (socket->cepid != 0) {
+		if (socket->input != NULL) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void udp_fd_delete(struct SHELL_FILE *fp)
+{
+	//socket_t *socket = (socket_t *)fp->exinf;
+	//free(socket->buf);
+	//socket->buf = NULL;
+	free(fp->exinf);
+	fp->exinf = NULL;
+}
+
+ER socket_udp_callback(ID cepid, FN fncd, void *p_parblk)
+{
+	struct SHELL_FILE *fp = id_to_fd(&IO_TYPE_UDP, cepid);
+	FLGPTN flgptn = 0;
+	int len;
+
+	if (fp == NULL)
+		return E_PAR;
+
+	int fd = fp->fd;
+	FD_SET(fd, (fd_set *)&flgptn);
+
+	switch (fncd) {
+	case TEV_UDP_RCV_DAT:
+	{
+		T_UDP_RCV_DAT_PARA *udppara = (T_UDP_RCV_DAT_PARA *)p_parblk;
+		len = udppara->len;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		ER ret = wai_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "wai_sem => %d", ret);
+		}
+		socket_t *socket = (socket_t *)fp->exinf;
+		socket->len = len;
+		if (socket->input != NULL) {
+			ret = rel_net_buf(socket->input);
+			if (ret < 0) {
+				syslog(LOG_ERROR, "rel_net_buf => %d", ret);
+			}
+		}
+		socket->input = udppara->input;
+		socket->buf = GET_UDP_SDU(udppara->input, udppara->off);
+		memset(&socket->raddr4, 0, sizeof(socket->raddr4));
+		socket->raddr4.sin_family = AF_INET;
+		socket->raddr4.sin_port = htons(udppara->rep4.portno);
+		socket->raddr4.sin_addr.s_addr = htonl(udppara->rep4.ipaddr);
+		udppara->input->flags |= NB_FLG_NOREL_IFOUT;
+		ret = sig_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "sig_sem => %d", ret);
+		}
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+	}
+	case TFN_UDP_CRE_CEP:
+		return E_OK;
+
+	case TFN_UDP_RCV_DAT:
+		len = *(int *)p_parblk;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_UDP_SND_DAT:
+		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_UDP_CAN_CEP:
+		if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_UDP_DEL_CEP:
+		delete_fd_by_id(&IO_TYPE_UDP, cepid);
+		return E_OK;
+
+	default:
+		return E_OK;
+	}
+}
+
+ER socket_udp6_callback(ID cepid, FN fncd, void *p_parblk)
+{
+	struct SHELL_FILE *fp = id_to_fd(&IO_TYPE_UDP, cepid);
+	FLGPTN flgptn = 0;
+	int len;
+
+	if (fp == NULL)
+		return E_PAR;
+
+	int fd = fp->fd;
+	FD_SET(fd, (fd_set *)&flgptn);
+
+	switch (fncd) {
+	case TEV_UDP_RCV_DAT:
+	{
+		T_UDP_RCV_DAT_PARA *udppara = (T_UDP_RCV_DAT_PARA *)p_parblk;
+		len = udppara->len;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		ER ret = wai_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "wai_sem => %d", ret);
+		}
+		socket_t *socket = (socket_t *)fp->exinf;
+		socket->len = len;
+		if (socket->input != NULL) {
+			ret = rel_net_buf(socket->input);
+			if (ret < 0) {
+				syslog(LOG_ERROR, "rel_net_buf => %d", ret);
+			}
+		}
+		socket->input = udppara->input;
+		socket->buf = GET_UDP_SDU(udppara->input, udppara->off);
+		memset(&socket->raddr6, 0, sizeof(socket->raddr6));
+		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
+		udppara->input->flags |= NB_FLG_NOREL_IFOUT;
+		ret = sig_sem(SEM_FILEDESC);
+		if (ret < 0) {
+			syslog(LOG_ERROR, "sig_sem => %d", ret);
+		}
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+	}
+	case TFN_UDP_CRE_CEP:
+		return E_OK;
+
+	case TFN_UDP_RCV_DAT:
+		len = *(int *)p_parblk;
+		if ((len <= 0) || (fp->exinf == NULL))
+			return E_OK;
+
+		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_UDP_SND_DAT:
+		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_UDP_CAN_CEP:
+		if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
+
+		set_flg(FLG_SELECT_WAIT, flgptn);
+		return E_OK;
+
+	case TFN_UDP_DEL_CEP:
+		delete_fd_by_id(&IO_TYPE_UDP, cepid);
+		return E_OK;
+
+	default:
+		return E_OK;
+	}
 }
 
