/* FUNCTION: bsd_setsockopt() * * Set a socket option value * * PARAM1: s; IN - socket descriptor * PARAM2: level; IN - the level of the option to set * PARAM3: name; IN - the name of the option to set * PARAM4: opt; OUT - ptr to buffer containing option value; may be * NULL * PARAM5: optlen; IN - specifies the length in bytes of the option * value in opt * RETURNS: 0 if successful, -1 if an error occurred. The error is * available via bsd_errno(s). */ int bsd_setsockopt(BSD_SOCKET s, int level, int name, void * opt, int optlen) { struct socket * so; so = LONG2SO(s); SOC_CHECK(so); /* make sure supplied option value is big enough for the * named option, else fail w/error EFAULT */ if (optlen < bsd_i_sockoptlen(level, name)) { so->so_error = EFAULT; return -1; } return t_setsockopt(s, level, name, opt, optlen); }
/* * FUNCTION: bsd_ioctl() * * Perform a control operation on a socket * * PARAM1: s; IN - socket descriptor * PARAM2: request; IN - requested control operation * PARAM3: arg; IN/OUT - arguments as required for control operation * RETURNS: 0 if successful, -1 if an error occurred. The error is * available via bsd_errno(s). */ int bsd_ioctl(BSD_SOCKET s, unsigned long request, ...) { struct socket * so; va_list argptr; int iarg; so = LONG2SO(s); SOC_CHECK(so); va_start(argptr, request); switch (request) { case FIONBIO: iarg = va_arg(argptr, int); va_end(argptr); return t_setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &iarg, sizeof(iarg)); default: so->so_error = EINVAL; return -1; } }
void tcp_echo_recv(void) { int len; /* length of recv data */ int e; /* error holder */ unsigned i; /* generic index */ int count; /* select return */ fd_set fd_recv; /* fd for recv */ fd_set fd_accept; /* fd for accept */ TCPCLIENT tmpclient = tcpq; struct sockaddr_in client; SOCKTYPE tmpsock; /* scratch socket */ if (elisten_sock == INVALID_SOCKET && tcpq == NULL) return; /* Echo not set up, don't bother */ #ifdef USE_FDS FD_ZERO(&fd_recv); FD_ZERO(&fd_accept); #endif /* select on all open data sockets */ i = 0; count = 0; #ifdef USE_FDS while (tmpclient) { if (tmpclient->sock != INVALID_SOCKET) { FD_SET(tmpclient->sock, &fd_recv); i++; } tmpclient=tmpclient->next; } #else while (tmpclient) { if (tmpclient->sock != INVALID_SOCKET) fd_recv.fd_array[i++] = tmpclient->sock ; tmpclient=tmpclient->next; } #endif /* USE_FDS */ #ifndef TCP_ZEROCOPY /* if we need to listen for server receives too */ #ifdef USE_FDS if (tcpecho_server && (esvr_sock != INVALID_SOCKET)) { FD_SET(esvr_sock, &fd_recv); } #else if (tcpecho_server) { if (esvr_sock != INVALID_SOCKET) fd_recv.fd_array[i++] = esvr_sock; } #endif /* USE_FDS */ #else /* if we need to close the server's active socket */ if (esvr_sock_close != FALSE) { if (esvr_sock != INVALID_SOCKET) { socketclose(esvr_sock); esvr_sock = INVALID_SOCKET; } esvr_sock_close = FALSE; } #endif /* TCP_ZEROCOPY */ #ifndef USE_FDS fd_recv.fd_count = i; #endif /* make this a short timeout since elisten may create soon */ if (elisten_sock != INVALID_SOCKET) { #ifdef USE_FDS FD_SET(elisten_sock, &fd_accept); #else fd_accept.fd_array[0] = elisten_sock; fd_accept.fd_count = 1; #endif /* USE_FDS */ count = t_select(&fd_recv, NULL, &fd_accept, 1); } else { if (i) /* if no fd_set sockets filled in, don't bother */ count = t_select(&fd_recv, NULL, NULL, 1); } /* While the t_select() was executing, commands can be * executed from cmd-prompt and sockets can be cleaned up. * Check for that. */ if (elisten_sock == INVALID_SOCKET && tcpq == NULL) return; /* Echo not set up, don't bother */ for (i = 0; i < fd_recv.fd_count; i++) { #ifdef USE_FDS tmpsock = FD_GET(i, &fd_recv); if (tmpsock == INVALID_SOCKET) continue; #else tmpsock = fd_recv.fd_array[i]; #endif /* USE_FDS */ /* Find out the client connection corresponding to this socket */ tmpclient = tcp_client_from_sock(tmpsock); /* try a receive. Pick buffer according to client or server */ if (tmpclient) /* found a client for this one */ len = recv(tmpsock, tmpclient->inbuf, ECHOBUFSIZE, 0); #ifndef TCP_ZEROCOPY else if (tmpsock == esvr_sock) len = recv(tmpsock, srv_inbuf, ECHOBUFSIZE, 0); #endif /* TCP_ZEROCOPY */ else { continue; } if (len < 0) { e = t_errno(tmpsock); if (e != EWOULDBLOCK) { if (tmpsock != esvr_sock) ns_printf(tmpclient->pio,"TCP echo recv error %d\n", e); else ns_printf(NULL,"TCP echo recv error %d\n", e); } } else if (len == 0) { ns_printf(NULL,"TCPECHO:socket closed by other side\n"); if (tmpsock == esvr_sock) { socketclose (tmpsock); esvr_sock = INVALID_SOCKET; } else { if (tmpclient == NULL) { dtrap(); } else { tmpclient->sock = INVALID_SOCKET ; tcp_client_del(tmpclient); } } } else /* if (len > 0) - got some echo data */ { #ifndef TCP_ZEROCOPY if (tmpsock == esvr_sock) { /* we must be server, send echo reply */ if (tcpecho_server) { e = send(esvr_sock, srv_inbuf, len, 0); if (e < 0) { /* Print the error to console */ e = t_errno(esvr_sock); ns_printf(NULL, "TCP echo server, error %d sending reply\n", e); } } } else /* not the server socket, must be client */ #endif /* TCP_ZEROCOPY */ { /* If not a bulk test, print info */ if (tmpclient->len <= ECHOBUFSIZE) { ns_printf(tmpclient->pio,"TCP echo reply from:%s, len:%d, reply:%lu", print_ipad(tmpclient->rhost), len, tmpclient->replies); ns_printf(tmpclient->pio,"\n%s",prompt); } else { u_long dataval; u_long * rxbuf = (u_long*)(tmpclient->inbuf); u_long * rxend = (u_long*)(tmpclient->inbuf + (len & ~3)); dataval = tmpclient->tot_rcvd/4; /* adjust for odd sized previous receives */ if (tmpclient->tot_rcvd & 3) { MEMMOVE(rxbuf, tmpclient->inbuf + (len & 3), len); rxend--; dataval++; /* ignore sliced word */ } while (rxbuf < rxend) { if (*rxbuf != dataval) { ns_printf(tmpclient->pio, "tcp_echo data error; got %lu, expected %lu\n", *rxbuf, dataval); } rxbuf++; dataval++; } } tmpclient->replies++; tmpclient->tot_rcvd += len; } } } /* if no server listen to poll, return now */ if (elisten_sock == INVALID_SOCKET) return; #ifdef NOTDEF MEMSET(&client, 0, sizeof(client)); client.sin_family = AF_INET; client.sin_addr.s_addr = INADDR_ANY; client.sin_port = htons(ECHO_PORT); #endif /* check for received echo connection on server */ len = sizeof(client); tmpsock = accept(elisten_sock, (struct sockaddr*)&client, &len); if (tmpsock != INVALID_SOCKET) { if (esvr_sock == INVALID_SOCKET) { esvr_sock = tmpsock; #ifdef TCP_ZEROCOPY t_setsockopt(esvr_sock, SOL_SOCKET, SO_CALLBACK, (void*)echo_svr_upcall, 0); #endif /* TCP_ZEROCOPY */ } else /* we already have a connection */ { dprintf("tcpecho: rejected extra connection\n"); socketclose(tmpsock); /* refuse to serve another */ } } }
int tcp_sendecho(void * pio, ip_addr fhost, /* already in net endian */ long len, long times) { struct sockaddr_in sa; int e; SOCKTYPE tmp; TCPCLIENT tcpclient; /* If client socket isn't open or host has changed, open it */ tcpclient = tcp_client_from_pio(pio); if (tcpclient == NULL) /* not found */ { if ((e=tcp_client_add(pio)) != SUCCESS) { if (e == TCPE_ALL_SOCKS_USED) { ns_printf(pio,"All TCP Echo Client connections are in use.\n"); ns_printf(pio,"Please try at a later time.\n"); } return e; } tcpclient = tcp_client_from_pio(pio); } if (tcpclient->sock == INVALID_SOCKET || fhost != tcpclient->rhost) { int opt; if (tcpclient->sock != INVALID_SOCKET) /* host changed */ { socketclose(tcpclient->sock); tcpclient->sock=INVALID_SOCKET; } /* (re)open new socket to client for echo */ tmp = socket(AF_INET, SOCK_STREAM, 0); if (tmp == INVALID_SOCKET) { ns_printf(pio,"tcp echo: can't open socket\n"); tcp_client_del(tcpclient); return TCPE_CANT_OPEN_SOCKET ; } e = t_setsockopt(tmp, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); sa.sin_family = AF_INET; /* host is already in network endian */ sa.sin_addr.s_addr = tcpclient->rhost = fhost; sa.sin_port = htons(ECHO_PORT); e = connect(tmp, (struct sockaddr*)&sa, sizeof(sa)); if (e != 0) { e = t_errno(tmp); ns_printf(pio,"tcp_echo: bad socket connect: %d %s\n", e, so_perror(e)); tcp_client_del(tcpclient); return TCPE_CONNECT_FAILED ; } /* Put in non-block mode */ sock_noblock(tmp, TRUE); tcpclient->sock = tmp; } tcpclient->replies = 0; tcpclient->times = times; tcpclient->delay = pingdelay; tcpclient->ticks = cticks; tcpclient->state = TCP_BUSY ; tcpclient->len = len ; tcpclient->send_cnt = 0 ; return tcp_send_an_echo(tcpclient); }
int tcp_secho_init(void * pio) { int e; /* error holder */ struct sockaddr_in me; /* my IP info, for bind() */ int opt; if (tcpecho_server) { ns_printf(pio,"tcp echo srv - starting.\n"); /* open TCP socket */ elisten_sock = socket(AF_INET, SOCK_STREAM, 0); if (elisten_sock == INVALID_SOCKET) { ns_printf(pio,"TCP echo: bad socket: %d\n", elisten_sock); return TCPE_BAD_SOCKET ; } opt = 1; e = t_setsockopt(elisten_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (e != 0) { e = t_errno(elisten_sock); dtrap(); dprintf("error %d setting SO_REUSEADDR on port %d\n", e, ECHO_PORT); return SYS_SOCKETNULL; } me.sin_family = AF_INET; me.sin_addr.s_addr = INADDR_ANY; me.sin_port = htons(ECHO_PORT); e = bind(elisten_sock, (struct sockaddr*)&me, sizeof(me)); if (e != 0) { e = t_errno(elisten_sock); ns_printf(pio,"tcp_echo: bad socket bind: %d, %s\n", e, so_perror(e)); socketclose(elisten_sock); elisten_sock = INVALID_SOCKET; return TCPE_BIND_FAILED ; } e = listen(elisten_sock, 3); if (e != 0) { e = t_errno(elisten_sock); ns_printf(pio,"tcp_echo: bad socket listen: %d %s\n", e, so_perror(e)); socketclose(elisten_sock); elisten_sock = INVALID_SOCKET; return TCPE_LISTEN_FAILED; } /* for listen socket into Non-blocking mode so we can poll accept */ sock_noblock(elisten_sock, TRUE); } else ns_printf(pio,"tcp echo server not enabled\n"); srv_inbuf = (char *)npalloc(ECHOBUFSIZE); if (srv_inbuf == NULL) { ns_printf(pio, "tcp server: alloc failed\n"); socketclose(elisten_sock); elisten_sock = INVALID_SOCKET; return TCPE_LISTEN_FAILED; } return SUCCESS; }
HTCPCONN tcp_ipv6_server_init(unsigned short p_usPort, void * arg ) { gFunctions = (T_PFN_functions *)arg; SOCKTYPE sock = t_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { C_NLOG_ERR("Iniche:tcp_ipv6_server_init: couldn't create ip6 socket"); return NULL; } //add sock in array int i = 0; int isSett = 0; for(;i < MAX_SOCK_NO; i++) { if(g_sockets[i].sock == INVALID_SOCKET) { g_sockets[i].sock = sock; g_sockets[i].indxToListen = -1; isSett = 1; break; } } if(isSett == 0) { t_socketclose(sock); C_NLOG_ERR("Iniche:tcp_ipv6_server_init: couldn't create ip6 socket."); return NULL; } struct sockaddr_in6 tcpsin6; int addrlen = sizeof(tcpsin6); IP6CPY(&tcpsin6.sin6_addr, &in6addr_any); tcpsin6.sin6_port = htons(p_usPort); tcpsin6.sin6_family = AF_INET6; int e = t_bind(g_sockets[i].sock, (struct sockaddr *)&tcpsin6, addrlen); if (e != 0) { e = t_errno(g_sockets[i].sock); t_socketclose(g_sockets[i].sock); g_sockets[i].sock = INVALID_SOCKET; C_NLOG_ERR("Iniche:tcp_ipv6_server_init: error %d binding tcp listen on port %d",e, p_usPort); return NULL; } int iTmp = 1; e = t_setsockopt(g_sockets[i].sock, SOL_SOCKET, SO_NONBLOCK, (void *)&iTmp, sizeof(iTmp)); if (e == SOCKET_ERROR) { e = t_errno(g_sockets[i].sock); t_socketclose(g_sockets[i].sock); g_sockets[i].sock = INVALID_SOCKET; C_NLOG_ERR("Iniche:tcp_ipv6_server_init: t_setsockopt() SO_NONBLOCK failed, Err: %d", e); return NULL; } e = t_listen(g_sockets[i].sock,MAX_SOCK_NO); if (e != 0) { e = t_errno(g_sockets[i].sock); t_socketclose(g_sockets[i].sock); g_sockets[i].sock = INVALID_SOCKET; C_NLOG_ERR("Iniche:tcp_ipv6_server_init: error %d tcp can't listen on port %d",e, p_usPort); return NULL; } C_NLOG_INFO( "Iniche:tcp_ipv6_server_init: TCP server initialized successfully." ); return (HTCPCONN)(g_sockets+i); }
void tcp_ipv6_poll() { int indx = 0; int freeSlot = 0; for(; indx<MAX_SOCK_NO; indx++) if(g_sockets[indx].indxToListen == -1) { int sa_size = sizeof(struct sockaddr_in6); struct sockaddr_in6 stFrom; SOCKTYPE sock = t_accept(g_sockets[indx].sock,(struct sockaddr*)&stFrom, &sa_size); //C_NLOG_INFO("Iniche:tcp_ipv6_poll: 0"); if(sock <= 0) continue; //C_NLOG_INFO("Iniche:tcp_ipv6_poll: 1"); //C_NLOG_INFO("Iniche:tcp_ipv6_poll: 2"); int iTmp = 1; int e = t_setsockopt(sock, SOL_SOCKET, SO_NONBLOCK, (void *)&iTmp, sizeof(iTmp)); if (e == SOCKET_ERROR) { e = t_errno(sock); t_socketclose(sock); C_NLOG_ERR("Iniche:tcp_ipv6_pool: t_setsockopt() SO_NONBLOCK failed, Err: %d", e); continue; } iTmp = INICHE_TCP_RCV_MAX_BUFF_LEN; e = t_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&iTmp, sizeof(iTmp)); if (e == SOCKET_ERROR) { e = t_errno(sock); t_socketclose(sock); C_NLOG_ERR("Iniche:tcp_ipv6_pool: t_setsockopt() SO_RCVBUF failed, Err: %d", e); continue; } int isSett = 0; for(; freeSlot < MAX_SOCK_NO; freeSlot++) { if(g_sockets[freeSlot].sock == INVALID_SOCKET) { //callback g_sockets[freeSlot].sock = sock; g_sockets[freeSlot].indxToListen = indx; (gFunctions->m_pfnAccept)((void *)(g_sockets+freeSlot)); //C_NLOG_INFO("Iniche:tcp_ipv6_poll: HCONN accepted = %X, index=%d",sock,freeSlot); isSett = 1; break; } } //if no free slot founded, then break if(isSett == 0) { C_NLOG_ERR("Iniche:tcp_ipv6_poll: No free slot for creating soket !"); t_socketclose(sock); break; } //C_NLOG_INFO("Iniche:tcp_ipv6_poll: 4"); } unsigned char buff[INICHE_TCP_RCV_MAX_BUFF_LEN]; int j = 0; for(; j < MAX_SOCK_NO; j++) { if(g_sockets[j].indxToListen != -1) { if(g_sockets[j].sock == INVALID_SOCKET) { continue; } int len = t_recv(g_sockets[j].sock, (char*)buff, INICHE_TCP_RCV_MAX_BUFF_LEN, 0); if(len > 0) { //C_NLOG_INFO("Iniche:tcp_ipv6_poll: 6 len = %d, buff=%s", len, (char*)buff); (gFunctions->m_pfnRecv)((void*)(g_sockets+j),buff,len); } } } }