/* FIXME: we should save client ipaddr into c->ipaddr after accept */ static int dbs_verify_ipaddr(char const * addrlist, t_d2dbs_connection * c) { char * adlist; char * s, *temp; t_elem * elem; t_d2dbs_connection * tempc; unsigned int valid; unsigned int resolveipaddr; adlist = xstrdup(addrlist); temp = adlist; valid = 0; while ((s = strsep(&temp, ","))) { host_lookup(s, &resolveipaddr); if (resolveipaddr == 0) continue; if (c->ipaddr == resolveipaddr) { valid = 1; break; } } xfree(adlist); if (valid) { eventlog(eventlog_level_info, __FUNCTION__, "ip address %s is valid", addr_num_to_ip_str(c->ipaddr)); LIST_TRAVERSE(dbs_server_connection_list, elem) { if (!(tempc = (t_d2dbs_connection*)elem_get_data(elem))) continue; if (tempc != c && tempc->ipaddr == c->ipaddr) { eventlog(eventlog_level_info, __FUNCTION__, "destroying previous connection %d", tempc->serverid); dbs_server_shutdown_connection(tempc); list_remove_elem(dbs_server_connection_list, &elem); } } c->verified = 1; return 0; } else {
void dbs_server_loop(int lsocket) { struct sockaddr_in sinRemote; int sd ; fd_set ReadFDs, WriteFDs, ExceptFDs; t_elem * elem; t_d2dbs_connection* it; BOOL bOK ; const char* pcErrorType ; struct timeval tv; int highest_fd; psock_t_socklen nAddrSize = sizeof(sinRemote); while (1) { #ifdef WIN32 if (g_ServiceStatus<0 && kbhit() && getch()=='q') d2dbs_signal_quit_wrapper(); if (g_ServiceStatus == 0) d2dbs_signal_quit_wrapper(); while (g_ServiceStatus == 2) Sleep(1000); #endif if (d2dbs_handle_signal()<0) break; dbs_handle_timed_events(); highest_fd=dbs_server_setup_fdsets(&ReadFDs, &WriteFDs, &ExceptFDs, lsocket); tv.tv_sec = 0; tv.tv_usec = SELECT_TIME_OUT; switch (psock_select(highest_fd+1, &ReadFDs, &WriteFDs, &ExceptFDs, &tv) ) { case -1: eventlog(eventlog_level_error,__FUNCTION__,"psock_select() failed : %s",strerror(psock_errno())); continue; case 0: continue; default: break; } if (PSOCK_FD_ISSET(lsocket, &ReadFDs)) { sd = psock_accept(lsocket, (struct sockaddr*)&sinRemote, &nAddrSize); if (sd == -1) { eventlog(eventlog_level_error,__FUNCTION__,"psock_accept() failed : %s",strerror(psock_errno())); return; } eventlog(eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .", inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd); eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .", inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd); setsockopt_keepalive(sd); dbs_server_list_add_socket(sd, ntohl(sinRemote.sin_addr.s_addr)); if (psock_ctl(sd,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not set TCP socket [%d] to non-blocking mode (closing connection) (psock_ctl: %s)", sd,strerror(psock_errno())); psock_close(sd); } } else if (PSOCK_FD_ISSET(lsocket, &ExceptFDs)) { eventlog(eventlog_level_error,__FUNCTION__,"exception on listening socket"); /* FIXME: exceptions are not errors with TCP, they are out-of-band data */ return; } LIST_TRAVERSE(dbs_server_connection_list,elem) { bOK = TRUE; pcErrorType = 0; if (!(it=elem_get_data(elem))) continue; if (PSOCK_FD_ISSET(it->sd, &ExceptFDs)) { bOK = FALSE; pcErrorType = "General socket error"; /* FIXME: no no no no no */ PSOCK_FD_CLR(it->sd, &ExceptFDs); } else { if (PSOCK_FD_ISSET(it->sd, &ReadFDs)) { bOK = dbs_server_read_data(it); pcErrorType = "Read error"; PSOCK_FD_CLR(it->sd, &ReadFDs); } if (PSOCK_FD_ISSET(it->sd, &WriteFDs)) { bOK = dbs_server_write_data(it); pcErrorType = "Write error"; PSOCK_FD_CLR(it->sd, &WriteFDs); } } if (!bOK) { int err; psock_t_socklen errlen; err = 0; errlen = sizeof(err); if (psock_getsockopt(it->sd, PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)==0) { if (errlen && err!=0) { eventlog(eventlog_level_error,__FUNCTION__,"data socket error : %s",strerror(err)); } } dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } else { if (dbs_packet_handle(it)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"dbs_packet_handle() failed"); dbs_server_shutdown_connection(it); list_remove_elem(dbs_server_connection_list,&elem); } } } }