Exemple #1
0
	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 */
	}
Exemple #2
0
extern int udptest_send(t_connection const * c)
{
    t_packet *         upacket;
    struct sockaddr_in caddr;
    unsigned int       tries,successes;

    memset(&caddr,0,sizeof(caddr));
    caddr.sin_family = PSOCK_AF_INET;
    caddr.sin_port = htons(conn_get_game_port(c));
    caddr.sin_addr.s_addr = htonl(conn_get_game_addr(c));

    for (tries=successes=0; successes!=2 && tries<5; tries++)
    {
        if (!(upacket = packet_create(packet_class_udp)))
        {
            eventlog(eventlog_level_error,"udptest_send","[%d] could not allocate memory for packet",conn_get_socket(c));
            continue;
        }
        packet_set_size(upacket,sizeof(t_server_udptest));
        packet_set_type(upacket,SERVER_UDPTEST);
        bn_int_tag_set(&upacket->u.server_udptest.bnettag,BNETTAG);

        if (hexstrm)
        {
            fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] ",
                    conn_get_game_socket(c),
                    packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket),
                    packet_get_type_str(upacket,packet_dir_from_server),packet_get_type(upacket));
            fprintf(hexstrm,"from=%s ",
                    addr_num_to_addr_str(conn_get_game_addr(c),conn_get_game_port(c)));
            fprintf(hexstrm,"to=%s ",
                    addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)));
            fprintf(hexstrm,"length=%u\n",
                    packet_get_size(upacket));
            hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket));
        }

        if (psock_sendto(conn_get_game_socket(c),
                         packet_get_raw_data_const(upacket,0),packet_get_size(upacket),
                         0,(struct sockaddr *)&caddr,(psock_t_socklen)sizeof(caddr))!=(int)packet_get_size(upacket))
            eventlog(eventlog_level_error,"udptest_send","[%d] failed to send UDPTEST to %s (attempt %u) (psock_sendto: %s)",conn_get_socket(c),addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),conn_get_game_port(c)),tries+1,strerror(psock_errno()));
        else
            successes++;

        packet_del_ref(upacket);
    }

    if (successes!=2)
        return -1;

    return 0;
}
Exemple #3
0
extern t_addr * addr_create_num(unsigned int ipaddr, unsigned short port)
#endif
{
    t_addr * temp;
    
#ifdef USE_CHECK_ALLOC
    if (!(temp = check_malloc_real(sizeof(t_addr),fn,ln)))
#else
    if (!(temp = malloc(sizeof(t_addr))))
#endif
    {
	eventlog(eventlog_level_error,"addr_create_num","unable to allocate memory for addr");
	return NULL;
    }
    
    if (!(temp->str = strdup(addr_num_to_addr_str(ipaddr,port))))
    {
	eventlog(eventlog_level_error,"addr_create_num","could not allocate memory for str");
	free(temp);
	return NULL;
    }
    temp->str    = NULL;
    temp->ip     = ipaddr;
    temp->port   = port;
    temp->data.p = NULL;
    
    return temp;
}
Exemple #4
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))) {
		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)));
	}
Exemple #5
0
/* IP:port */
extern char * addr_get_addr_str(t_addr const * addr, char * str, unsigned int len)
{
    if (!addr)
    {
	eventlog(eventlog_level_error,"addr_get_addr_str","got NULL addr");
	return NULL;
    }
    if (!str)
    {
	eventlog(eventlog_level_error,"addr_get_addr_str","got NULL str");
	return NULL;
    }
    if (len<2)
    {
	eventlog(eventlog_level_error,"addr_get_addr_str","str too short");
	return NULL;
    }
    
    strncpy(str,addr_num_to_addr_str(addr->ip,addr->port),len-1);
    str[len-1] = '\0';
    
    return str;
}
Exemple #6
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);
	}
Exemple #7
0
extern int handle_init_packet(t_connection * c, t_packet const * const packet)
{
    if (!c)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c));
	return -1;
    }
    if (!packet)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c));
	return -1;
    }
    if (packet_get_class(packet)!=packet_class_init)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet));
        return -1;
    }
    
    switch (packet_get_type(packet))
    {
    case CLIENT_INITCONN:
	switch (bn_byte_get(packet->u.client_initconn.class))
	{
	case CLIENT_INITCONN_CLASS_BNET:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated bnet connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_bnet);

	    break;

	case CLIENT_INITCONN_CLASS_FILE:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated file download connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_file);
	    
	    break;
	    
	case CLIENT_INITCONN_CLASS_BOT:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated chat bot connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_bot);
	    
	    break;
	    
	case CLIENT_INITCONN_CLASS_TELNET:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated telnet connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_telnet);
	    
	    break;

        case CLIENT_INITCONN_CLASS_D2CS_BNETD:
            {
              eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated d2cs_bnetd connection",conn_get_socket(c));

              if (!(realmlist_find_realm_by_ip(conn_get_addr(c))))
              {
                 eventlog(eventlog_level_info,__FUNCTION__, "[%d] d2cs connection from unknown ip address %s",conn_get_socket(c),addr_num_to_addr_str(conn_get_addr(c),conn_get_port(c)));
                 return -1;
              }

              conn_set_state(c,conn_state_connected);
              conn_set_class(c,conn_class_d2cs_bnetd);
              if (handle_d2cs_init(c)<0)
              {
                  eventlog(eventlog_level_info,__FUNCTION__,"faild to init d2cs connection");
                  return -1;
              }
           }
           break;
	    
	case CLIENT_INITCONN_CLASS_ENC:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated encrypted connection (not supported)",conn_get_socket(c));
	    return -1;

	default:
	    eventlog(eventlog_level_error,__FUNCTION__,"[%d] client requested unknown class 0x%02x (length %d) (closing connection)",conn_get_socket(c),(unsigned int)bn_byte_get(packet->u.client_initconn.class),packet_get_size(packet));
	    return -1;
	}
	break;
    default:
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown init packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet));
	return -1;
    }
    
    return 0;
}
Exemple #8
0
		BOOL CALLBACK KickDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
		{
			switch (Message) {
			case WM_INITDIALOG:
				if (selected_item[0] != 0) {
					SetDlgItemText(hwnd, IDC_EDITKICK, selected_item);
				}

				return TRUE;
			case WM_COMMAND:
				switch (LOWORD(wParam)) {
				case IDC_KICK_EXECUTE:
				{
										 t_connection * conngui;
										 t_account * accountgui;
										 BOOL messageq;
										 BOOL kickq;
										 char temp[60];
										 char ipadr[110];

										 messageq = FALSE;
										 kickq = FALSE;

										 GetDlgItemText(hwnd, IDC_EDITKICK, selected_item, 32);

										 conngui = connlist_find_connection_by_accountname(selected_item);
										 accountgui = accountlist_find_account(selected_item);

										 if (conngui == NULL) {
											 strcat(selected_item, " could not be found in Userlist!");
											 MessageBox(hwnd, selected_item, "ERROR", MB_OK);
										 }
										 else {

											 HWND hButton = GetDlgItem(hwnd, IDC_CHECKBAN);
											 HWND hButton1 = GetDlgItem(hwnd, IDC_CHECKKICK);
											 HWND hButton2 = GetDlgItem(hwnd, IDC_CHECKADMIN);
											 HWND hButton3 = GetDlgItem(hwnd, IDC_CHECKMOD);
											 HWND hButton4 = GetDlgItem(hwnd, IDC_CHECKANN);

											 if (SendMessage(hButton2, BM_GETCHECK, 0, 0) == BST_CHECKED) {
												 account_set_admin(accountgui);
												 account_set_command_groups(accountgui, 255);
												 messageq = TRUE;
											 }

											 if (SendMessage(hButton3, BM_GETCHECK, 0, 0) == BST_CHECKED) {
												 account_set_auth_operator(accountgui, NULL, 1);
												 messageq = TRUE;
											 }

											 if (SendMessage(hButton4, BM_GETCHECK, 0, 0) == BST_CHECKED) {
												 account_set_strattr(accountgui, "BNET\\auth\\announce", "true");
												 messageq = TRUE;
											 }

											 if (SendMessage(hButton, BM_GETCHECK, 0, 0) == BST_CHECKED) {
												 unsigned int	i_GUI;

												 strcpy(temp, addr_num_to_addr_str(conn_get_addr(conngui), 0));

												 for (i_GUI = 0; temp[i_GUI] != ':'; i_GUI++)
													 ipadr[i_GUI] = temp[i_GUI];

												 ipadr[i_GUI] = 0;

												 strcpy(temp, " a ");
												 strcat(temp, ipadr);
												 handle_ipban_command(NULL, temp);

												 temp[0] = 0;
												 strcpy(temp, " has been added to IpBanList");
												 strcat(ipadr, temp);
												 if (messageq == TRUE) {
													 strcat(ipadr, " and UserStatus changed");
													 MessageBox(hwnd, ipadr, "ipBan & StatusChange", MB_OK);
													 messageq = FALSE;
													 kickq = FALSE;
												 }
												 else
													 MessageBox(hwnd, ipadr, "ipBan", MB_OK);
											 }

											 if (SendMessage(hButton1, BM_GETCHECK, 0, 0) == BST_CHECKED) {
												 conn_set_state(conngui, conn_state_destroy);
												 kickq = TRUE;
											 }

											 if ((messageq == TRUE) && (kickq == TRUE)) {
												 strcat(selected_item, "has been kicked and Status has changed");
												 MessageBox(hwnd, selected_item, "UserKick & StatusChange", MB_OK);
											 }

											 if ((kickq == TRUE) && (messageq == FALSE)) {
												 strcat(selected_item, " has been kicked from the server");
												 MessageBox(hwnd, selected_item, "UserKick", MB_OK);
											 }

											 if ((kickq == FALSE) && (messageq == TRUE)) {
												 strcat(selected_item, "'s Status has been changed");
												 MessageBox(hwnd, selected_item, "StatusChange", MB_OK);
											 }

											 selected_item[0] = 0;
										 }
										 break;
				}
				}
				break;
			case WM_CLOSE:
				EndDialog(hwnd, IDC_EDITKICK);
				break;
			default:
				return FALSE;
			}
			return TRUE;
		}
Exemple #9
0
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;
    }
  }
}
Exemple #10
0
static int sd_udpinput(t_addr *const curr_laddr, const t_laddr_info *laddr_info,
		       int ssocket, int usocket)
{
  int             err;
  psock_t_socklen errlen;
  t_packet *      upacket;

  if (laddr_info == NULL) {
    (void)ssocket;
  }
  err = 0;
  errlen = sizeof(err);
  if (psock_getsockopt(usocket,PSOCK_SOL_SOCKET,PSOCK_SO_ERROR,&err,&errlen)<0)
  {
    eventlog(eventlog_level_error,"sd_udpinput","[%d] unable to read socket error (psock_getsockopt: %s)",usocket,strerror(psock_errno()));
    return -1;
  }
  if (errlen && err) /* if it was an error, there is no packet to read */
  {
    eventlog(eventlog_level_error,"sd_udpinput","[%d] async UDP socket error notification (psock_getsockopt: %s)",usocket,strerror(err));
    return -1;
  }
  if (!(upacket = packet_create(packet_class_udp)))
  {
    eventlog(eventlog_level_error,"sd_udpinput","could not allocate raw packet for input");
    return -1;
  }

  {
    struct sockaddr_in fromaddr;
    psock_t_socklen    fromlen;
    int                len;

    fromlen = sizeof(fromaddr);
    if ((len = psock_recvfrom(usocket,packet_get_raw_data_build(upacket,0),MAX_PACKET_SIZE,0,(struct sockaddr *)&fromaddr,&fromlen))<0)
    {
      if (
#ifdef PSOCK_EINTR
	  psock_errno()!=PSOCK_EINTR &&
#endif
#ifdef PSOCK_EAGAIN
	  psock_errno()!=PSOCK_EAGAIN &&
#endif
#ifdef PSOCK_EWOULDBLOCK
	  psock_errno()!=PSOCK_EWOULDBLOCK &&
#endif
	  1)
	eventlog(eventlog_level_error,"sd_udpinput","could not recv UDP datagram (psock_recvfrom: %s)",strerror(psock_errno()));
      packet_del_ref(upacket);
      return -1;
    }

    if (fromaddr.sin_family!=PSOCK_AF_INET)
    {
      eventlog(eventlog_level_error,"sd_udpinput","got UDP datagram with bad address family %d",(int)fromaddr.sin_family);
      packet_del_ref(upacket);
      return -1;
    }

    packet_set_size(upacket,len);

    if (hexstrm)
    {
      char tempa[32];

      if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa)))
	strcpy(tempa,"x.x.x.x:x");
      fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] from=%s to=%s length=%u\n",
	      usocket,
	      packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket),
	      packet_get_type_str(upacket,packet_dir_from_client),packet_get_type(upacket),
	      addr_num_to_addr_str(ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port)),
	      tempa,
	      packet_get_size(upacket));
      hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket));
    }

    handle_udp_packet(usocket,ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port),upacket);
    packet_del_ref(upacket);
  }

  return 0;
}
Exemple #11
0
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;
}