Example #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 */
	}
void turn_channel_delete(ch_info* chn)
{
	if(chn) {
	  turn_permission_info* tinfo = (turn_permission_info*)chn->owner;
		if(tinfo) {
			ur_map_del(tinfo->channels, (ur_map_key_type)addr_get_port(&(chn->peer_addr)),NULL);
			delete_channel_info_from_allocation_map((ur_map_key_type)addr_get_port(&(chn->peer_addr)),(ur_map_value_type)chn);
		}
	}
}
Example #3
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)));
	}
ch_info* allocation_get_new_ch_info(allocation* a, u16bits chnum, ioa_addr* peer_addr)
{

	turn_permission_info* tinfo = get_from_turn_permission_map(a->addr_to_perm, peer_addr);

	if (!tinfo)
		tinfo = allocation_add_permission(a, peer_addr);

	ch_info* chn = (ch_info*)turn_malloc(sizeof(ch_info));

	ns_bzero(chn,sizeof(ch_info));

	chn->chnum = chnum;
	chn->port = addr_get_port(peer_addr);
	addr_cpy(&(chn->peer_addr), peer_addr);
	chn->owner = tinfo;
	ur_map_put(a->channel_to_ch_info, chnum, chn);

	ur_map_put(tinfo->channels, (ur_map_key_type) addr_get_port(peer_addr), (ur_map_value_type) chn);

	return chn;
}
Example #5
0
void turnipports_release(turnipports* tp, u08bits transport, const ioa_addr *socket_addr)
{
	if (tp && socket_addr) {
		ioa_addr ba;
		ur_addr_map_value_type t;
		addr_cpy(&ba, socket_addr);
		addr_set_port(&ba, 0);
		TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
		if (ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
			turnports_release((turnports*) t, addr_get_port(socket_addr));
		}
		TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
	}
}
ch_info *get_turn_channel(turn_permission_info* tinfo, ioa_addr *addr)
{
	if (tinfo) {
		ur_map_value_type t = 0;
		if (ur_map_get(tinfo->channels, (ur_map_key_type)addr_get_port(addr), &t) && t) {
			ch_info* chn = (ch_info*) t;
			if (STUN_VALID_CHANNEL(chn->chnum)) {
				return chn;
			}
		}
	}

	return NULL;
}
Example #7
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);
	}
Example #8
0
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;
}
Example #9
0
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));
	    }
Example #10
0
/* 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;
}
Example #11
0
int start_connection(uint16_t clnet_remote_port0,
		     const char *remote_address0,
		     const unsigned char* ifname, const char *local_address,
		     int verbose,
		     app_ur_conn_info *clnet_info_probe,
		     app_ur_conn_info *clnet_info,
		     uint16_t *chn,
		     app_ur_conn_info *clnet_info_rtcp,
		     uint16_t *chn_rtcp) {

	ioa_addr relay_addr;
	ioa_addr relay_addr_rtcp;
	ioa_addr peer_addr_rtcp;

	addr_cpy(&peer_addr_rtcp,&peer_addr);
	addr_set_port(&peer_addr_rtcp,addr_get_port(&peer_addr_rtcp)+1);

	/* Probe: */

	if (clnet_connect(clnet_remote_port0, remote_address0, ifname, local_address,
			verbose, clnet_info_probe) < 0) {
		exit(-1);
	}

	uint16_t clnet_remote_port = clnet_remote_port0;
	char remote_address[1025];
	STRCPY(remote_address,remote_address0);

	clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port);

	/* Real: */

	*chn = 0;
	if(chn_rtcp) *chn_rtcp=0;

	if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address,
			verbose, clnet_info) < 0) {
	  exit(-1);
	}

	if(!no_rtcp) {
	  if (clnet_connect(clnet_remote_port, remote_address, ifname, local_address,
			  verbose, clnet_info_rtcp) < 0) {
	    exit(-1);
	  }
	}

	int af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr);
	if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL) < 0) {
	  exit(-1);
	}

	if(rare_event()) return 0;

	if(!no_rtcp) {
		af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr_rtcp);
	  if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL) < 0) {
	    exit(-1);
	  }
	  if(rare_event()) return 0;
	}

	if (!dos) {
		if (!do_not_use_channel) {
			/* These multiple "channel bind" requests are here only because
			 * we are playing with the TURN server trying to screw it */
			if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr_rtcp)
					< 0) {
				exit(-1);
			}
			if(rare_event()) return 0;

			if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr_rtcp)
					< 0) {
				exit(-1);
			}
			if(rare_event()) return 0;
			*chn = 0;
			if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr) < 0) {
				exit(-1);
			}

			if(rare_event()) return 0;
			if (turn_channel_bind(verbose, chn, clnet_info, &peer_addr) < 0) {
				exit(-1);
			}
			if(rare_event()) return 0;

			if(extra_requests) {
				const char *sarbaddr = "164.156.178.190";
				if(random() % 2 == 0)
					sarbaddr = "2001::172";
				ioa_addr arbaddr;
				make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr);
				int i;
				int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS;
				for(i=0;i<maxi;i++) {
					u16bits chni=0;
					int port = (unsigned short)random();
					if(port<1024) port += 1024;
					addr_set_port(&arbaddr, port);
					u08bits *u=(u08bits*)&(arbaddr.s4.sin_addr);
					u[(unsigned short)random()%4] = u[(unsigned short)random()%4] + 1;
					//char sss[128];
					//addr_to_string(&arbaddr,(u08bits*)sss);
					//printf("%s: 111.111: %s\n",__FUNCTION__,sss);
					turn_channel_bind(verbose, &chni, clnet_info, &arbaddr);
				}
			}

			if (!no_rtcp) {
				if (turn_channel_bind(verbose, chn_rtcp, clnet_info_rtcp,
						&peer_addr_rtcp) < 0) {
					exit(-1);
				}
			}
			if(rare_event()) return 0;

			if(extra_requests) {
				const char *sarbaddr = "64.56.78.90";
				if(random() % 2 == 0)
					sarbaddr = "2001::172";
				ioa_addr arbaddr[EXTRA_CREATE_PERMS];
				make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr[0]);
				int i;
				int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS;
				for(i=0;i<maxi;i++) {
					if(i>0)
						addr_cpy(&arbaddr[i],&arbaddr[0]);
					addr_set_port(&arbaddr[i], (unsigned short)random());
					u08bits *u=(u08bits*)&(arbaddr[i].s4.sin_addr);
					u[(unsigned short)random()%4] = u[(unsigned short)random()%4] + 1;
					//char sss[128];
					//addr_to_string(&arbaddr[i],(u08bits*)sss);
					//printf("%s: 111.111: %s\n",__FUNCTION__,sss);
				}
				turn_create_permission(verbose, clnet_info, arbaddr, maxi);
			}
		} else {

			int before=(random()%2 == 0);

			if(before) {
				if (turn_create_permission(verbose, clnet_info, &peer_addr, 1) < 0) {
					exit(-1);
				}
				if(rare_event()) return 0;
				if (turn_create_permission(verbose, clnet_info, &peer_addr_rtcp, 1)
						< 0) {
					exit(-1);
				}
				if(rare_event()) return 0;
			}

			if(extra_requests) {
				const char *sarbaddr = "64.56.78.90";
				if(random() % 2 == 0)
					sarbaddr = "2001::172";
				ioa_addr arbaddr[EXTRA_CREATE_PERMS];
				make_ioa_addr((const u08bits*)sarbaddr, 333, &arbaddr[0]);
				int i;
				int maxi = (unsigned short)random() % EXTRA_CREATE_PERMS;
				for(i=0;i<maxi;i++) {
					if(i>0)
						addr_cpy(&arbaddr[i],&arbaddr[0]);
					addr_set_port(&arbaddr[i], (unsigned short)random());
					u08bits *u=(u08bits*)&(arbaddr[i].s4.sin_addr);
					u[(unsigned short)random()%4] = u[(unsigned short)random()%4] + 1;
					//char sss[128];
					//addr_to_string(&arbaddr,(u08bits*)sss);
					//printf("%s: 111.111: %s\n",__FUNCTION__,sss);
				}
				turn_create_permission(verbose, clnet_info, arbaddr, maxi);
			}

			if(!before) {
				if (turn_create_permission(verbose, clnet_info, &peer_addr, 1) < 0) {
					exit(-1);
				}
				if(rare_event()) return 0;
				if (turn_create_permission(verbose, clnet_info, &peer_addr_rtcp, 1)
					< 0) {
					exit(-1);
				}
				if(rare_event()) return 0;
			}

			if (!no_rtcp) {
				if (turn_create_permission(verbose, clnet_info_rtcp,
						&peer_addr_rtcp, 1) < 0) {
					exit(-1);
				}
				if(rare_event()) return 0;
				if (turn_create_permission(verbose, clnet_info_rtcp, &peer_addr, 1)
						< 0) {
					exit(-1);
				}
				if(rare_event()) return 0;
			}
		}
	}

	addr_cpy(&(clnet_info->peer_addr), &peer_addr);
	if(!no_rtcp) 
	  addr_cpy(&(clnet_info_rtcp->peer_addr), &peer_addr_rtcp);

	return 0;
}
Example #12
0
static int clnet_allocate(int verbose,
		app_ur_conn_info *clnet_info,
		ioa_addr *relay_addr,
		int af,
		char *turn_addr, u16bits *turn_port) {

	int af_cycle = 0;
	int reopen_socket = 0;

	int allocate_finished;

	stun_buffer request_message, response_message;

	beg_allocate:

	allocate_finished=0;

	while (!allocate_finished && af_cycle++ < 32) {

		int allocate_sent = 0;

		if(reopen_socket && !use_tcp) {
			socket_closesocket(clnet_info->fd);
			clnet_info->fd = -1;
			if (clnet_connect(addr_get_port(&(clnet_info->remote_addr)), clnet_info->rsaddr, (u08bits*)clnet_info->ifname, clnet_info->lsaddr,
					verbose, clnet_info) < 0) {
				exit(-1);
			}
			reopen_socket = 0;
		}

		int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4);
		int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6);

		uint64_t reservation_token = 0;
		char* rt = NULL;
		int ep = !no_rtcp && !dual_allocation;

		if(!no_rtcp) {
			if (!never_allocate_rtcp && allocate_rtcp) {
				reservation_token = ioa_ntoh64(current_reservation_token);
				rt = (char*) (&reservation_token);
			}
		}

		if(is_TCP_relay()) {
			ep = -1;
		} else if(rt) {
			ep = -1;
		} else if(!ep) {
			ep = (((u08bits)random()) % 2);
			ep = ep-1;
		}

		if(!dos)
			stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility, rt, ep);
		else
			stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility, rt, ep);

		if(bps)
			stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps);

		if(dont_fragment)
			stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0);

		add_origin(&request_message);

		if(add_integrity(clnet_info, &request_message)<0) return -1;

		stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len));

		while (!allocate_sent) {

			int len = send_buffer(clnet_info, &request_message,0,0);

			if (len > 0) {
				if (verbose) {
					TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate sent\n");
				}
				allocate_sent = 1;
			} else {
				perror("send");
				exit(1);
			}
		}

		////////////<<==allocate send

		if(not_rare_event()) return 0;

		////////allocate response==>>
		{
			int allocate_received = 0;
			while (!allocate_received) {

				int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message);

				if (len > 0) {
					if (verbose) {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
								"allocate response received: \n");
					}
					response_message.len = len;
					int err_code = 0;
					u08bits err_msg[129];
					if (stun_is_success_response(&response_message)) {
						allocate_received = 1;
						allocate_finished = 1;

						if(clnet_info->nonce[0]) {
							if(check_integrity(clnet_info, &response_message)<0)
								return -1;
						}

						if (verbose) {
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n");
						}
						{
							int found = 0;

							stun_attr_ref sar = stun_attr_get_first(&response_message);
							while (sar) {

								int attr_type = stun_attr_get_type(sar);
								if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) {

									if (stun_attr_get_addr(&response_message, sar, relay_addr, NULL) < 0) {
										TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
											"%s: !!!: relay addr cannot be received (1)\n",
											__FUNCTION__);
										return -1;
									} else {
										if (verbose) {
											ioa_addr raddr;
											memcpy(&raddr, relay_addr,sizeof(ioa_addr));
											addr_debug_print(verbose, &raddr,"Received relay addr");
										}

										if(!addr_any(relay_addr)) {
											if(relay_addr->ss.sa_family == AF_INET) {
												if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) {
													found = 1;
													addr_cpy(&(clnet_info->relay_addr),relay_addr);
													break;
												}
											}
											if(relay_addr->ss.sa_family == AF_INET6) {
												if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) {
													found = 1;
													addr_cpy(&(clnet_info->relay_addr),relay_addr);
													break;
												}
											}
										}
									}
								}

								sar = stun_attr_get_next(&response_message,sar);
							}

							if(!found) {
								TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
										"%s: !!!: relay addr cannot be received (2)\n",
										__FUNCTION__);
								return -1;
							}
						}

						stun_attr_ref rt_sar = stun_attr_get_first_by_type(
								&response_message, STUN_ATTRIBUTE_RESERVATION_TOKEN);
						uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar);
						current_reservation_token = rtv;
						if (verbose)
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
								      "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv);

						read_mobility_ticket(clnet_info, &response_message);

					} else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len,
									&err_code,err_msg,sizeof(err_msg),
									clnet_info->realm,clnet_info->nonce,
									clnet_info->server_name, &(clnet_info->oauth))) {
						goto beg_allocate;
					} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {

						allocate_received = 1;

						if(err_code == 300) {

							if(clnet_info->nonce[0]) {
								if(check_integrity(clnet_info, &response_message)<0)
									return -1;
							}

							ioa_addr alternate_server;
							if(stun_attr_get_first_addr(&response_message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) {
								//error
							} else if(turn_addr && turn_port){
								addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr);
								*turn_port = (u16bits)addr_get_port(&alternate_server);
							}

						}

						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n",
								      err_code,(char*)err_msg);
						if (err_code != 437) {
							allocate_finished = 1;
							current_reservation_token = 0;
							return -1;
						} else {
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
									"trying allocate again %d...\n", err_code);
							sleep(1);
							reopen_socket = 1;
						}
					} else {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
									"unknown allocate response\n");
						/* Try again ? */
					}
				} else {
					perror("recv");
					exit(-1);
					break;
				}
			}
		}
	}
	////////////<<== allocate response received

	if(rare_event()) return 0;

	if(!allocate_finished) {
	  TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
			"Cannot complete Allocation\n");
	  exit(-1);
	}

	allocate_rtcp = !allocate_rtcp;

	if (1) {

	  af_cycle = 0;

	  if(clnet_info->s_mobile_id[0]) {

		  int fd = clnet_info->fd;
		  SSL* ssl = clnet_info->ssl;

		  int close_now = (int)(random()%2);

		  if(close_now) {
			  int close_socket = (int)(random()%2);
			  if(ssl && !close_socket) {
				  SSL_shutdown(ssl);
				  SSL_FREE(ssl);
				  fd = -1;
			  } else if(fd>=0) {
				  close(fd);
				  fd = -1;
				  ssl = NULL;
			  }
		  }

		  app_ur_conn_info ci;
		  ns_bcopy(clnet_info,&ci,sizeof(ci));
		  ci.fd = -1;
		  ci.ssl = NULL;
		  clnet_info->fd = -1;
		  clnet_info->ssl = NULL;
		  //Reopen:
		  if(clnet_connect(addr_get_port(&(ci.remote_addr)), ci.rsaddr,
		  		(unsigned char*)ci.ifname, ci.lsaddr, clnet_verbose,
		  		clnet_info)<0) {
			  exit(-1);
		  }

		  if(ssl) {
			  SSL_shutdown(ssl);
		  	  SSL_FREE(ssl);
		  } else if(fd>=0) {
		  	  close(fd);
		  }
	  }

		beg_refresh:

	  if(af_cycle++>32) {
	    TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
			  "Cannot complete Refresh\n");
	    exit(-1);
	  }

		//==>>refresh request, for an example only:
		{
			int refresh_sent = 0;

			stun_init_request(STUN_METHOD_REFRESH, &request_message);
			uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME);
			stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) &lt, 4);

			if(clnet_info->s_mobile_id[0]) {
				stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id));
			}

			if(dual_allocation && !mobility) {
				int t = ((u08bits)random())%3;
				if(t) {
					u08bits field[4];
					field[0] = (t==1) ? (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4 : (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
					field[1]=0;
					field[2]=0;
					field[3]=0;
					stun_attr_add(&request_message, STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY, (const char*) field, 4);
				}
			}

			add_origin(&request_message);

			if(add_integrity(clnet_info, &request_message)<0) return -1;

			stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len));

			while (!refresh_sent) {

				int len = send_buffer(clnet_info, &request_message, 0,0);

				if (len > 0) {
					if (verbose) {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh sent\n");
					}
					refresh_sent = 1;

					if(clnet_info->s_mobile_id[0]) {
						usleep(10000);
						send_buffer(clnet_info, &request_message, 0,0);
					}
				} else {
					perror("send");
					exit(1);
				}
			}
		}

		if(not_rare_event()) return 0;

		////////refresh response==>>
		{
			int refresh_received = 0;
			while (!refresh_received) {

				int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message);

				if(clnet_info->s_mobile_id[0]) {
					len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message);
				}

				if (len > 0) {
					if (verbose) {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
								"refresh response received: \n");
					}
					response_message.len = len;
					int err_code = 0;
					u08bits err_msg[129];
					if (stun_is_success_response(&response_message)) {
						read_mobility_ticket(clnet_info, &response_message);
						refresh_received = 1;
						if (verbose) {
							TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n");
						}
					} else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len,
										&err_code,err_msg,sizeof(err_msg),
										clnet_info->realm,clnet_info->nonce,
										clnet_info->server_name, &(clnet_info->oauth))) {
						goto beg_refresh;
					} else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) {
						refresh_received = 1;
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n",
								      err_code,(char*)err_msg);
						return -1;
					} else {
						TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "unknown refresh response\n");
						/* Try again ? */
					}
				} else {
					perror("recv");
					exit(-1);
					break;
				}
			}
		}
	}

	return 0;
}
Example #13
0
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;
}
Example #14
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;
    }
  }
}
Example #15
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;
}