static int server_listen(void) { t_addr * curr_laddr; t_addr_data laddr_data; int sock; if (!(server_listen_addrs=addrlist_create(prefs_get_servaddrs(),INADDR_ANY,D2CS_SERVER_PORT))) { eventlog(eventlog_level_error,__FUNCTION__,"error create listening address list"); return -1; } BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr) { sock=net_listen(addr_get_ip(curr_laddr),addr_get_port(curr_laddr),PSOCK_SOCK_STREAM); if (sock<0) { eventlog(eventlog_level_error,__FUNCTION__,"error listen socket"); return -1; } if (psock_ctl(sock,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error set listen socket in non-blocking mode"); } laddr_data.i = sock; addr_set_data(curr_laddr,laddr_data); if (fdwatch_add_fd(sock, fdwatch_type_read, d2cs_server_handle_accept, curr_laddr)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",sock); psock_close(sock); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"listen on %s", addr_num_to_addr_str(addr_get_ip(curr_laddr),addr_get_port(curr_laddr))); }
extern int trans_net(unsigned int clientaddr, unsigned int *addr, unsigned short *port) { t_elem const *curr; t_trans *entry; char temp1[32]; char temp2[32]; char temp3[32]; char temp4[32]; #ifdef DEBUG_TRANS eventlog(eventlog_level_debug, __FUNCTION__, "checking %s for client %s ...", addr_num_to_addr_str(*addr, *port), addr_num_to_ip_str(clientaddr)); #endif if (trans_head) { LIST_TRAVERSE_CONST(trans_head, curr) { if (!(entry = (t_trans*)elem_get_data(curr))) { eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list"); continue; } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug, __FUNCTION__, "against entry -> %s output %s network %s", addr_get_addr_str(entry->input, temp1, sizeof(temp1)), addr_get_addr_str(entry->output, temp2, sizeof(temp2)), netaddr_get_addr_str(entry->network, temp3, sizeof(temp3))); #endif if (addr_get_ip(entry->input) != *addr || addr_get_port(entry->input) != *port) { #ifdef DEBUG_TRANS eventlog(eventlog_level_debug, __FUNCTION__, "entry does match input address"); #endif continue; } if (netaddr_contains_addr_num(entry->network, clientaddr) == 0) { #ifdef DEBUG_TRANS eventlog(eventlog_level_debug, __FUNCTION__, "client is not in the correct network"); #endif continue; } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug, __FUNCTION__, "%s translated to %s", addr_num_to_addr_str(*addr, *port), addr_get_addr_str(entry->output, temp4, sizeof(temp4))); #endif *addr = addr_get_ip(entry->output); *port = addr_get_port(entry->output); return 1; /* match found in list */ } } #ifdef DEBUG_TRANS eventlog(eventlog_level_debug, __FUNCTION__, "no match found for %s (not translated)", addr_num_to_addr_str(*addr, *port)); #endif return 0; /* no match found in list */ }
int addr_compare(const addr_t *src, const addr_t *dst) { char ip1[MAX_IP_STR_LEN]; char ip2[MAX_IP_STR_LEN]; int ret; addr_get_ip(src, ip1); addr_get_ip(dst, ip2); if (strcmp(ip1, ip2) == 0) ret = true; else ret = false; return ret; }
bool addr_is_loopback(const addr_t *addr) { static const char *IPV4_LOOPBACK = "127.0.0.1"; static const char *IPV6_LOOPBACK = "0:0:0:0:0:0:0:1"; static const char *IPV6_LOOPBACK_SIMPLE = "::1"; char ip[MAX_IP_STR_LEN]; addr_get_ip(addr, ip); if (addr_get_type(addr) == ADDR_IPV4) return strcmp(ip, IPV4_LOOPBACK) == 0; else return strcmp(ip, IPV6_LOOPBACK) == 0 || strcmp(ip, IPV6_LOOPBACK_SIMPLE) == 0; }
static int server_listen(void) { t_addr * curr_laddr; t_addr_data laddr_data; int sock; if (!(server_listen_addrs=addrlist_create(prefs_get_servaddrs(),INADDR_ANY,D2CS_SERVER_PORT))) { log_error("error create listening address list"); return -1; } BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr) { sock=net_listen(addr_get_ip(curr_laddr),addr_get_port(curr_laddr),PSOCK_SOCK_STREAM); if (sock<0) { log_error("error listen socket"); return -1; } log_info("listen on %s", addr_num_to_addr_str(addr_get_ip(curr_laddr),addr_get_port(curr_laddr))); if (psock_ctl(sock,PSOCK_NONBLOCK)<0) { log_error("error set listen socket in non-blocking mode"); } laddr_data.p=(void *)sock; addr_set_data(curr_laddr,laddr_data); }
t_list * realmlist_load(char const * filename) { FILE * fp; unsigned int line; unsigned int pos; unsigned int len; t_addr * raddr; char * temp, *temp2; char * buff; char * name; char * desc; t_realm * realm; t_list * list_head = NULL; if (!filename) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename"); return NULL; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open realm file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno)); return NULL; } list_head = list_create(); for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { continue; } if ((temp = strrchr(buff,'#'))) { unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } /* skip any separators */ for (temp = buff; *temp && (*temp == ' ' || *temp == '\t');temp++); if (*temp != '"') { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename); continue; } temp2 = temp + 1; /* find the next " */ for (temp = temp2; *temp && *temp != '"';temp++); if (*temp != '"' || temp == temp2) { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename); continue; } /* save the realmname */ *temp = '\0'; name = xstrdup(temp2); /* eventlog(eventlog_level_trace, __FUNCTION__,"found realmname: %s",name); */ /* skip any separators */ for(temp = temp + 1; *temp && (*temp == '\t' || *temp == ' ');temp++); if (*temp == '"') { /* we have realm description */ temp2 = temp + 1; /* find the next " */ for(temp = temp2;*temp && *temp != '"';temp++); if (*temp != '"' || temp == temp2) { eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no valid description)",line,filename); xfree(name); continue; } /* save the description */ *temp = '\0'; desc = xstrdup(temp2); /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm desc: %s",desc); */ /* skip any separators */ for(temp = temp + 1; *temp && (*temp == ' ' || *temp == '\t');temp++); } else desc = xstrdup("\0"); temp2 = temp; /* find out where address ends */ for(temp = temp2 + 1; *temp && *temp != ' ' && *temp != '\t';temp++); if (*temp) *temp++ = '\0'; /* if is not the end of the file, end addr and move forward */ /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm ip: %s",temp2); */ if (!(raddr = addr_create_str(temp2,0,BNETD_REALM_PORT))) /* 0 means "this computer" */ { eventlog(eventlog_level_error,__FUNCTION__,"invalid address value for field 3 on line %u in file \"%s\"",line,filename); xfree(name); xfree(desc); continue; } if (!(realm = realm_create(name,desc,addr_get_ip(raddr),addr_get_port(raddr)))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create realm"); addr_destroy(raddr); xfree(name); xfree(desc); continue; } addr_destroy(raddr); xfree(name); xfree(desc); list_prepend_data(list_head,realm); } file_get_line(NULL); // clear file_get_line buffer if (fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close realm file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno)); return list_head; }
extern int tracker_send_report(t_addrlist const * laddrs) { t_addr const * addrl; t_elem const * currl; t_addr const * addrt; t_elem const * currt; t_trackpacket packet; struct utsname utsbuf; struct sockaddr_in tempaddr; t_laddr_info * laddr_info; char tempa[64]; char tempb[64]; if (addrlist_get_length(track_servers)>0) { std::memset(&packet,0,sizeof(packet)); bn_short_nset(&packet.packet_version,(unsigned short)TRACK_VERSION); /* packet.port is set below */ bn_int_nset(&packet.flags, 0); std::strncpy((char *)packet.server_location, prefs_get_location(), sizeof(packet.server_location)); bn_byte_set(&packet.server_location[sizeof(packet.server_location)-1],'\0'); std::strncpy((char *)packet.software, PVPGN_SOFTWARE, sizeof(packet.software)); bn_byte_set(&packet.software[sizeof(packet.software)-1],'\0'); std::strncpy((char *)packet.version, PVPGN_VERSION, sizeof(packet.version)); bn_byte_set(&packet.version[sizeof(packet.version)-1],'\0'); std::strncpy((char *)packet.server_desc, prefs_get_description(), sizeof(packet.server_desc)); bn_byte_set(&packet.server_desc[sizeof(packet.server_desc)-1],'\0'); std::strncpy((char *)packet.server_url, prefs_get_url(), sizeof(packet.server_url)); bn_byte_set(&packet.server_url[sizeof(packet.server_url)-1],'\0'); std::strncpy((char *)packet.contact_name, prefs_get_contact_name(), sizeof(packet.contact_name)); bn_byte_set(&packet.contact_name[sizeof(packet.contact_name)-1],'\0'); std::strncpy((char *)packet.contact_email, prefs_get_contact_email(), sizeof(packet.contact_email)); bn_byte_set(&packet.contact_email[sizeof(packet.contact_email)-1],'\0'); bn_int_nset(&packet.users,connlist_login_get_length()); bn_int_nset(&packet.channels,channellist_get_length()); bn_int_nset(&packet.games,gamelist_get_length()); bn_int_nset(&packet.uptime,server_get_uptime()); bn_int_nset(&packet.total_logins,connlist_total_logins()); bn_int_nset(&packet.total_games,gamelist_total_games()); if (uname(&utsbuf)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"could not get platform info (uname: %s)",pstrerror(errno)); std::strncpy((char *)packet.platform,"",sizeof(packet.platform)); } else { std::strncpy((char *)packet.platform, utsbuf.sysname, sizeof(packet.platform)); bn_byte_set(&packet.platform[sizeof(packet.platform)-1],'\0'); } LIST_TRAVERSE_CONST(laddrs,currl) { addrl = (t_addr*)elem_get_data(currl); if (!(laddr_info = (t_laddr_info*)addr_get_data(addrl).p)) { eventlog(eventlog_level_error,__FUNCTION__,"address data is NULL"); continue; } if (laddr_info->type!=laddr_type_bnet) continue; /* don't report IRC, telnet, and other non-game ports */ bn_short_nset(&packet.port,addr_get_port(addrl)); LIST_TRAVERSE_CONST(track_servers,currt) { addrt = (t_addr*)elem_get_data(currt); std::memset(&tempaddr,0,sizeof(tempaddr)); tempaddr.sin_family = PSOCK_AF_INET; tempaddr.sin_port = htons(addr_get_port(addrt)); tempaddr.sin_addr.s_addr = htonl(addr_get_ip(addrt)); if (!addr_get_addr_str(addrl,tempa,sizeof(tempa))) std::strcpy(tempa,"x.x.x.x:x"); if (!addr_get_addr_str(addrt,tempb,sizeof(tempb))) std::strcpy(tempa,"x.x.x.x:x"); /* eventlog(eventlog_level_debug,__FUNCTION__,"sending tracking info from %s to %s",tempa,tempb); */ if (psock_sendto(laddr_info->usocket,&packet,sizeof(packet),0,(struct sockaddr *)&tempaddr,(psock_t_socklen)sizeof(tempaddr))<0) eventlog(eventlog_level_warn,__FUNCTION__,"could not send tracking information from %s to %s (psock_sendto: %s)",tempa,tempb,pstrerror(errno)); }
/* FIXME: No it doesn't! pcAddress is not ever referenced in this * function. * CreepLord: Fixed much better way (will accept dns hostnames) */ int dbs_server_init(void) { int sd; struct sockaddr_in sinInterface; int val; t_addr * servaddr; dbs_server_connection_list=list_create(); if (d2dbs_d2ladder_init()==-1) { eventlog(eventlog_level_error,__FUNCTION__,"d2ladder_init() failed"); return -1; } if (cl_init(DEFAULT_HASHTBL_LEN, DEFAULT_GS_MAX)==-1) { eventlog(eventlog_level_error,__FUNCTION__,"cl_init() failed"); return -1; } if (psock_init()<0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_init() failed"); return -1; } sd = psock_socket(PSOCK_PF_INET, PSOCK_SOCK_STREAM, PSOCK_IPPROTO_TCP); if (sd==-1) { eventlog(eventlog_level_error,__FUNCTION__,"psock_socket() failed : %s",strerror(psock_errno())); return -1; } val = 1; if (psock_setsockopt(sd, PSOCK_SOL_SOCKET, PSOCK_SO_REUSEADDR, &val, sizeof(val)) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_setsockopt() failed : %s",strerror(psock_errno())); } if (!(servaddr=addr_create_str(d2dbs_prefs_get_servaddrs(),INADDR_ANY,DEFAULT_LISTEN_PORT))) { eventlog(eventlog_level_error,__FUNCTION__,"could not get servaddr"); return -1; } sinInterface.sin_family = PSOCK_AF_INET; sinInterface.sin_addr.s_addr = htonl(addr_get_ip(servaddr)); sinInterface.sin_port = htons(addr_get_port(servaddr)); if (psock_bind(sd, (struct sockaddr*)&sinInterface, (psock_t_socklen)sizeof(struct sockaddr_in)) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_bind() failed : %s",strerror(psock_errno())); return -1; } if (psock_listen(sd, LISTEN_QUEUE) < 0) { eventlog(eventlog_level_error,__FUNCTION__,"psock_listen() failed : %s",strerror(psock_errno())); return -1; } addr_destroy(servaddr); return sd; }
extern int realmlist_create(char const * filename) { FILE * fp; unsigned int line; unsigned int pos; unsigned int len; t_addr * raddr; char * temp; char * buff; char * name; char * desc; char * addr; t_realm * realm; if (!filename) { eventlog(eventlog_level_error,"realmlist_create","got NULL filename"); return -1; } if (!(realmlist_head = list_create())) { eventlog(eventlog_level_error,"realmlist_create","could not create list"); return -1; } if (!(fp = fopen(filename,"r"))) { eventlog(eventlog_level_error,"realmlist_create","could not open realm file \"%s\" for reading (fopen: %s)",filename,strerror(errno)); list_destroy(realmlist_head); realmlist_head = NULL; return -1; } for (line=1; (buff = file_get_line(fp)); line++) { for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++); if (buff[pos]=='\0' || buff[pos]=='#') { free(buff); continue; } if ((temp = strrchr(buff,'#'))) { unsigned int endpos; *temp = '\0'; len = strlen(buff)+1; for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--); buff[endpos+1] = '\0'; } len = strlen(buff)+1; if (!(name = malloc(len))) { eventlog(eventlog_level_error,"realmlist_create","could not allocate memory for name"); free(buff); continue; } if (!(desc = malloc(len))) { eventlog(eventlog_level_error,"realmlist_create","could not allocate memory for desc"); free(name); free(buff); continue; } if (!(addr = malloc(len))) { eventlog(eventlog_level_error,"realmlist_create","could not allocate memory for desc"); free(desc); free(name); free(buff); continue; } if (sscanf(buff," \"%[^\"]\" \"%[^\"]\" %s",name,desc,addr)!=3) { if (sscanf(buff," \"%[^\"]\" \"\" %s",name,addr)==2) desc[0] = '\0'; else { eventlog(eventlog_level_error,"realmlist_create","malformed line %u in file \"%s\"",line,filename); free(addr); free(desc); free(name); free(buff); continue; } } free(buff); if (!(raddr = addr_create_str(addr,0,BNETD_REALM_PORT))) /* 0 means "this computer" */ { eventlog(eventlog_level_error,"realmlist_create","invalid address value for field 3 on line %u in file \"%s\"",line,filename); free(addr); free(desc); free(name); continue; } free(addr); if (!(realm = realm_create(name,desc,addr_get_ip(raddr),addr_get_port(raddr)))) { eventlog(eventlog_level_error,"realmlist_create","could not create realm"); addr_destroy(raddr); free(desc); free(name); continue; } addr_destroy(raddr); free(desc); free(name); if (list_prepend_data(realmlist_head,realm)<0) { eventlog(eventlog_level_error,"realmlist_create","could not prepend realm"); realm_destroy(realm); continue; } } if (fclose(fp)<0) eventlog(eventlog_level_error,"realmlist_create","could not close realm file \"%s\" after reading (fclose: %s)",filename,strerror(errno)); return 0; }
static void handle_dns_query(const uint8_t *raw_data, uint16_t data_len, socket_t *client_socket, const addr_t *client_addr, void *arg) { //header is 12 octets, wire name is 1 octets, //class is 2 octets, type is 2 octets if (data_len < 12 + 4 + 1) { log_warning(QUERY_LOG, "get invalid query package\n"); return; } if (dns_header_get_opt(raw_data) != QUERY_STAND) { log_warning(QUERY_LOG, "get non-query package\n"); return; } zipper_t *zipper = (zipper_t *)arg; query_session_t *session = memorypool_alloc_node(zipper->query_session_pool_); if (session == NULL) { log_warning(QUERY_LOG, "no memory left to handle more query\n"); return; } memcpy(session->query_raw_data_, raw_data, data_len); session->query_data_len_ = data_len; session->zipper_ = zipper; session->client_socket_ = *client_socket; session->client_addr_ = *client_addr; char ip_addr_str[MAX_IP_STR_LEN]; addr_get_ip(client_addr, ip_addr_str); log_debug(QUERY_LOG, "get query from ip [%s]\n", ip_addr_str); session->location_info_ = ipstore_get_location_use_int(zipper->ip_store_, addr_get_v4_addr(client_addr)); if (!session->location_info_) { log_warning(QUERY_LOG, "get ip failed\n"); goto BAD_QUERY; } buffer_t buf; buffer_create_from(&buf, (void *)(raw_data + 12), data_len - 12 - 4); session->query_wire_name_ = wire_name_from_wire(&buf); if (session->query_wire_name_) { buffer_t name_buf; char str_name[MAX_DOMAIN_NAME_LEN] = {0}; buffer_create_from(&name_buf, str_name, MAX_DOMAIN_NAME_LEN); wire_name_to_text(session->query_wire_name_, &name_buf); log_debug(QUERY_LOG, "handle query name [%s]\n", str_name); char view_name[MAX_VIEW_NAME_LEN]; rule_store_get_view(zipper->rule_store_, session->query_wire_name_, session->location_info_, view_name); query_named_with_view(view_name, session); wire_name_delete(session->query_wire_name_); } else { wire_name_delete(session->query_wire_name_); log_warning(QUERY_LOG, "get invalid query name\n"); goto BAD_QUERY; } return; BAD_QUERY: memorypool_free_node(zipper->query_session_pool_, session); }
extern void gametrans_net(unsigned int vaddr, unsigned short vport, unsigned int laddr, unsigned short lport, unsigned int * addr, unsigned short * port) { const t_elem *curr; t_gametrans *entry; #ifdef DEBUGGAMETRANS char temp1[32]; char temp2[32]; char temp3[32]; char temp4[32]; #endif #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","checking client %s (viewer on %s connected to %s)...", addr_num_to_addr_str(*addr,*port), addr_num_to_addr_str(vaddr,vport), addr_num_to_addr_str(laddr,lport)); #else (void)vport; #endif if (gametrans_head) { LIST_TRAVERSE_CONST(gametrans_head,curr) { if (!(entry = elem_get_data(curr))) { eventlog(eventlog_level_error,"gametrans_net","found NULL entry in list"); continue; } #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","against entry viewerint=%s client=%s output=%s viewerex=%s", addr_get_addr_str(entry->viewer,temp1,sizeof(temp1)), addr_get_addr_str(entry->client,temp2,sizeof(temp2)), addr_get_addr_str(entry->output,temp3,sizeof(temp3)), netaddr_get_addr_str(entry->exclude,temp4,sizeof(temp4))); #endif if (addr_get_ip(entry->viewer)!=0 && addr_get_ip(entry->viewer)!=laddr) { #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","viewer is not on right interface IP"); #endif continue; } if (addr_get_port(entry->viewer)!=0 && addr_get_port(entry->viewer)!=lport) { #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","view is not on right interface port"); #endif continue; } if (addr_get_ip(entry->client)!=0 && addr_get_ip(entry->client)!=*addr) { #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","client is not on the right IP"); #endif continue; } if (addr_get_port(entry->client)!=0 && addr_get_port(entry->client)!=*port) { #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","client is not on the right port"); #endif continue; } if (netaddr_contains_addr_num(entry->exclude,vaddr)==1) { #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","viewer is in the excluded network"); #endif continue; } *addr = addr_get_ip(entry->output); *port = addr_get_port(entry->output); #ifdef DEBUGGAMETRANS eventlog(eventlog_level_debug,"gametrans_net","did translation"); #endif return; } } }
static int sd_accept(t_addr const * curr_laddr, t_laddr_info const * laddr_info, int ssocket, int usocket) { char tempa[32]; int csocket; struct sockaddr_in caddr; psock_t_socklen caddr_len; unsigned int raddr; unsigned short rport; if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa))) strcpy(tempa,"x.x.x.x:x"); /* accept the connection */ memset(&caddr,0,sizeof(caddr)); /* not sure if this is needed... modern systems are ok anyway */ caddr_len = sizeof(caddr); if ((csocket = psock_accept(ssocket,(struct sockaddr *)&caddr,&caddr_len))<0) { /* BSD, POSIX error for aborted connections, SYSV often uses EAGAIN or EPROTO */ if ( #ifdef PSOCK_EWOULDBLOCK psock_errno()==PSOCK_EWOULDBLOCK || #endif #ifdef PSOCK_ECONNABORTED psock_errno()==PSOCK_ECONNABORTED || #endif #ifdef PSOCK_EPROTO psock_errno()==PSOCK_EPROTO || #endif 0) eventlog(eventlog_level_error,"sd_accept","client aborted connection on %s (psock_accept: %s)",tempa,strerror(psock_errno())); else /* EAGAIN can mean out of resources _or_ connection aborted :( */ if ( #ifdef PSOCK_EINTR psock_errno()!=PSOCK_EINTR && #endif 1) eventlog(eventlog_level_error,"sd_accept","could not accept new connection on %s (psock_accept: %s)",tempa,strerror(psock_errno())); return -1; } #ifdef HAVE_POLL if (csocket>=BNETD_MAX_SOCKETS) /* This check is a bit too strict (csocket is probably * greater than the number of connections) but this makes * life easier later. */ { eventlog(eventlog_level_error,"sd_accept","csocket is beyond range allowed by BNETD_MAX_SOCKETS for poll() (%d>=%d)",csocket,BNETD_MAX_SOCKETS); psock_close(csocket); return -1; } #else # ifdef FD_SETSIZE if (csocket>=FD_SETSIZE) /* fd_set size is determined at compile time */ { eventlog(eventlog_level_error,"sd_accept","csocket is beyond range allowed by FD_SETSIZE for select() (%d>=%d)",csocket,FD_SETSIZE); psock_close(csocket); return -1; } # endif #endif if (ipbanlist_check(inet_ntoa(caddr.sin_addr))!=0) { eventlog(eventlog_level_info,"sd_accept","[%d] connection from banned address %s denied (closing connection)",csocket,inet_ntoa(caddr.sin_addr)); psock_close(csocket); return -1; } eventlog(eventlog_level_info,"sd_accept","[%d] accepted connection from %s on %s",csocket,addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)),tempa); if (prefs_get_use_keepalive()) { int val=1; if (psock_setsockopt(csocket,PSOCK_SOL_SOCKET,PSOCK_SO_KEEPALIVE,&val,(psock_t_socklen)sizeof(val))<0) eventlog(eventlog_level_error,"sd_accept","[%d] could not set socket option SO_KEEPALIVE (psock_setsockopt: %s)",csocket,strerror(psock_errno())); /* not a fatal error */ } { struct sockaddr_in rsaddr; psock_t_socklen rlen; memset(&rsaddr,0,sizeof(rsaddr)); /* not sure if this is needed... modern systems are ok anyway */ rlen = sizeof(rsaddr); if (psock_getsockname(csocket,(struct sockaddr *)&rsaddr,&rlen)<0) { eventlog(eventlog_level_error,"sd_accept","[%d] unable to determine real local port (psock_getsockname: %s)",csocket,strerror(psock_errno())); /* not a fatal error */ raddr = addr_get_ip(curr_laddr); rport = addr_get_port(curr_laddr); } else { if (rsaddr.sin_family!=PSOCK_AF_INET) { eventlog(eventlog_level_error,"sd_accept","local address returned with bad address family %d",(int)rsaddr.sin_family); /* not a fatal error */ raddr = addr_get_ip(curr_laddr); rport = addr_get_port(curr_laddr); } else { raddr = ntohl(rsaddr.sin_addr.s_addr); rport = ntohs(rsaddr.sin_port); } } } if (psock_ctl(csocket,PSOCK_NONBLOCK)<0) { eventlog(eventlog_level_error,"sd_accept","[%d] could not set TCP socket to non-blocking mode (closing connection) (psock_ctl: %s)",csocket,strerror(psock_errno())); psock_close(csocket); return -1; } { t_connection * c; if (!(c = conn_create(csocket,usocket,raddr,rport,addr_get_ip(curr_laddr),addr_get_port(curr_laddr),ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)))) { eventlog(eventlog_level_error,"sd_accept","[%d] unable to create new connection (closing connection)",csocket); psock_close(csocket); return -1; } eventlog(eventlog_level_debug,"sd_accept","[%d] client connected to a %s listening address",csocket,laddr_type_get_str(laddr_info->type)); switch (laddr_info->type) { case laddr_type_irc: conn_set_class(c,conn_class_irc); conn_set_state(c,conn_state_connected); break; case laddr_type_telnet: conn_set_class(c,conn_class_telnet); conn_set_state(c,conn_state_connected); break; case laddr_type_bnet: default: /* We have to wait for an initial "magic" byte on bnet connections to * tell us exactly what connection class we are dealing with. */ break; } } return 0; }