enum proto_accept_error proto_accept_connection(int listener_fd, int *read_fd, int *write_fd, const char **name) { int timeout = server_int_option("name_lookup_timeout", 5); int fd; struct sockaddr_in *addr = (struct sockaddr_in *) call->addr.buf; static Stream *s = 0; if (!s) s = new_stream(100); fd = t_open((void *) "/dev/tcp", O_RDWR, 0); if (fd < 0) { if (t_errno == TSYSERR && errno == EMFILE) return PA_FULL; else { log_ti_error("Opening endpoint for new connection"); return PA_OTHER; } } if (t_bind(fd, 0, 0) < 0) { log_ti_error("Binding endpoint for new connection"); t_close(fd); return PA_OTHER; } if (t_listen(listener_fd, call) < 0) { log_ti_error("Accepting new network connection"); t_close(fd); return PA_OTHER; } if (t_accept(listener_fd, fd, call) < 0) { log_ti_error("Accepting new network connection"); t_close(fd); return PA_OTHER; } if (!set_rw_able(fd)) { t_close(fd); return PA_OTHER; } *read_fd = *write_fd = fd; stream_printf(s, "%s, port %d", lookup_name_from_addr(addr, timeout), (int) ntohs(addr->sin_port)); *name = reset_stream(s); return PA_OKAY; }
/* FUNCTION: bsd_accept() * * Accept a connection on a socket * * PARAM1: s; IN - socket descriptor for the listening socket * PARAM2: addr; OUT - ptr to buffer for return of accepted peer's address; * may be NULL if return of address is not requested * PARAM3: addrlen; IN/OUT - ptr to int; on entry, specifies the length * in bytes of addr; on successful return, specifies the * length of the returned address; may be NULL if * addr is also NULL * RETURNS: A socket descriptor if successful, -1 if an error occurred. * The error is available via bsd_errno(s). */ BSD_SOCKET bsd_accept(BSD_SOCKET s, struct sockaddr * addr, int * addrlen) { struct socket * so; struct sockaddr laddr; long lret; so = LONG2SO(s); SOC_CHECK(so); /* if we were given a buffer for the peer's address, also get the * buffer's length */ if (addr != NULL) { if (addrlen == 0) { so->so_error = EFAULT; return -1; } } lret = t_accept(s, &laddr, addrlen); /* if we were successful, and we were given a buffer for the peer's * address: copy the peer's address back into the buffer, but limit * the copy to the lesser of the buffer's length and sizeof(struct * sockaddr_in), which is all that t_accept() can return as a peer * address. */ if ((lret != -1) && (addr != NULL)) { if (*addrlen > sizeof(struct sockaddr_in)) *addrlen = sizeof(struct sockaddr_in); MEMCPY(addr, &laddr, *addrlen); } return lret; }
int accept_client(int fd, struct t_call *call) { int sd; if ((sd = t_open(DEV_XTI, O_RDWR, NULL)) < 0) error("serwer->accept_client->t_open", fd, sd); if (t_bind(sd, NULL, NULL) < 0) error("serwer->accept_client->t_bind", fd, sd); if (t_accept(fd, sd, call) < 0) { if (t_errno == TLOOK) { if (t_rcvdis(fd, NULL) < 0) error("serwer->accept_client->t_rcvdis", fd, sd); if (t_close(sd) < 0) error("serwer->accept_client->t_close", fd, sd); return -1; } error("t_accept failed", fd, sd); } return(sd); }
/* * This call attempts to t_accept() an incoming/pending TLI connection. * If it is thwarted by a TLOOK, it is deferred and whatever is on the * file descriptor, removed after a t_look. (Incoming connect indications * get queued for later processing and disconnect indications remove a * a queued connection request if a match found). * Returns -1 on failure, else 0. */ int tlx_accept(const char *fmri, tlx_info_t *tlx_info, struct sockaddr_storage *remote_addr) { tlx_conn_ind_t *conind; struct t_call *call; int fd; int listen_fd = tlx_info->pr_info.listen_fd; debug_msg("Entering tlx_accept: instance: %s", fmri); if ((fd = t_open(tlx_info->dev_name, O_RDWR, NULL)) == -1) { error_msg("t_open: %s", t_strerror(t_errno)); return (-1); } if (tlx_info->pr_info.v6only) { int on = 1; /* restrict to IPv6 communications only */ if (tlx_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) == -1) { (void) t_close(fd); return (-1); } } if (t_bind(fd, NULL, NULL) == -1) { error_msg("t_bind: %s", t_strerror(t_errno)); (void) t_close(fd); return (-1); } /* * Get the next connection indication - first try the pending * queue, then, if none there, get a new one from the file descriptor. */ if ((conind = uu_list_first(tlx_info->conn_ind_queue)) != NULL) { debug_msg("taking con off queue"); call = conind->call; } else if ((call = get_new_conind(listen_fd)) == NULL) { (void) t_close(fd); return (-1); } /* * Accept the connection indication on the newly created endpoint. * If we fail, and it's the result of a tlook, queue the indication * if it isn't already, and go and process the t_look. */ if (t_accept(listen_fd, fd, call) == -1) { if (t_errno == TLOOK) { if (uu_list_first(tlx_info->conn_ind_queue) == NULL) { /* * We are first one to have to defer accepting * and start the pending connections list. */ if (queue_conind(tlx_info->conn_ind_queue, call) == -1) { error_msg(gettext( "Failed to queue connection " "indication for instance %s"), fmri); (void) t_free((char *)call, T_CALL); return (-1); } } (void) process_tlook(fmri, tlx_info); } else { /* non-TLOOK accept failure */ error_msg("%s: %s", "t_accept failed", t_strerror(t_errno)); /* * If we were accepting a queued connection, dequeue * it. */ if (uu_list_first(tlx_info->conn_ind_queue) != NULL) (void) dequeue_conind(tlx_info->conn_ind_queue); (void) t_free((char *)call, T_CALL); } (void) t_close(fd); return (-1); } /* Copy remote address into address parameter */ (void) memcpy(remote_addr, call->addr.buf, MIN(call->addr.len, sizeof (*remote_addr))); /* If we were accepting a queued connection, dequeue it. */ if (uu_list_first(tlx_info->conn_ind_queue) != NULL) (void) dequeue_conind(tlx_info->conn_ind_queue); (void) t_free((char *)call, T_CALL); return (fd); }
static XtransConnInfo TRANS(TLIAccept)(XtransConnInfo ciptr, int *status) { struct t_call *call; XtransConnInfo newciptr; int i; prmsg(2,"TLIAccept(%x->%d)\n", ciptr, ciptr->fd); if( (call=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL ) { prmsg(1, "TLIAccept() failed to allocate a t_call\n"); *status = TRANS_ACCEPT_BAD_MALLOC; return NULL; } if( t_listen(ciptr->fd,call) < 0 ) { extern char *t_errlist[]; extern int t_errno; prmsg(1, "TLIAccept() t_listen() failed\n"); prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]); t_free((char *)call,T_CALL); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } /* * Now we need to set up the new endpoint for the incoming connection. */ i=ciptr->index; /* Makes the next line more readable */ if( (newciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL ) { prmsg(1, "TLIAccept() failed to open a new endpoint\n"); t_free((char *)call,T_CALL); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( TRANS(TLITLIBindLocal)(newciptr->fd,TLItrans2devtab[i].family,"") < 0 ) { prmsg(1, "TLIAccept: TRANS(TLITLIBindLocal)() failed: %d\n", errno); t_free((char *)call,T_CALL); t_close(newciptr->fd); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( t_accept(ciptr->fd,newciptr->fd,call) < 0 ) { extern char *t_errlist[]; extern int t_errno; prmsg(1, "TLIAccept() t_accept() failed\n"); prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]); if( t_errno == TLOOK ) { int evtype = t_look(ciptr->fd); prmsg(1, "TLIAccept() t_look() returned %d\n", evtype); switch( evtype ) { case T_DISCONNECT: if( t_rcvdis(ciptr->fd, NULL) < 0 ) { prmsg(1, "TLIAccept() t_rcvdis() failed\n"); prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]); } break; default: break; } } t_free((char *)call,T_CALL); t_close(newciptr->fd); free(newciptr); *status = TRANS_ACCEPT_FAILED; return NULL; } t_free((char *)call,T_CALL); if( TRANS(TLIGetAddr)(newciptr) < 0 ) { prmsg(1, "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n", errno); t_close(newciptr->fd); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( TRANS(TLIGetPeerAddr)(newciptr) < 0 ) { prmsg(1, "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n", errno); t_close(newciptr->fd); free(newciptr->addr); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( ioctl(newciptr->fd, I_POP,"timod") < 0 ) { prmsg(1, "TLIAccept() ioctl(I_POP, \"timod\") failed %d\n", errno); t_close(newciptr->fd); free(newciptr->addr); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( ioctl(newciptr->fd, I_PUSH,"tirdwr") < 0 ) { prmsg(1, "TLIAccept() ioctl(I_PUSH,\"tirdwr\") failed %d\n", errno); t_close(newciptr->fd); free(newciptr->addr); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } *status = 0; return newciptr; }
/* **************************************************************** * Aguarda pedidos de conexão (servidor) * **************************************************************** */ int tcp_listen (int fd, char *name) { T_CALL call; T_BIND bind; INADDR client_addr, addr[2]; int newfd; char *cp; /* * Preenche a estrutura T_CALL: só o membro addr é relevante. */ FILL_NETBUF (call.addr, &client_addr, sizeof (client_addr)); FILL_NETBUF (call.opt, NULL, 0); FILL_NETBUF (call.udata, NULL, 0); /* * Espera chegar um pedido de conexão. */ if (t_listen (fd, &call) < 0) return (-1); /* * Abre outro "endpoint". */ if ((newfd = t_open (tcpdevname, O_RDWR, (T_INFO *)NULL)) < 0) return (-1); /* * Preenche a estrutura T_BIND. */ if (client_addr.a_addr == LOCAL_IP_ADDR) { /* * A conexão é local: deixa o kernel gerar outro port. */ bind.addr.len = 0; bind.addr.buf = addr; bind.addr.maxlen = sizeof (INADDR); } else { /* * A conexão é remota: respeita o port do "t_listen". */ FILL_INADDR (addr[0], 0, listen_port); FILL_INADDR (addr[1], client_addr.a_addr, client_addr.a_port); FILL_NETBUF (bind.addr, addr, sizeof (addr)); } bind.qlen = 0; /* Não vamos dar "t_listen" nesta conexão */ if (t_bind (newfd, &bind, (T_BIND *)NULL) < 0) goto bad; if (set_param (newfd) < 0) goto bad; /* * Aceita a conexão no novo "endpoint". */ if (t_accept (fd, newfd, &call) < 0) goto bad; if ( name != NOSTR && (cp = t_addr_to_node (fd, client_addr.a_addr)) != NOSTR ) strcpy (name, cp); return (newfd); bad: t_close (newfd); return (-1); } /* end tcp_listen */
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); } } } }