Ejemplo n.º 1
0
static int cmp(const void *d1, const void *d2)
{
	struct netconn *nc1 = ((struct dataman *) d1)->nc;
	struct netconn *nc2 = ((struct dataman *) d1)->nc;

	int r = nc1->sock - nc2->sock;
	if (r != 0)
		return r;

	return sock_cmpaddr((struct sockaddr *) &nc1->addr,
			    (struct sockaddr *) &nc2->addr, 1);

}
Ejemplo n.º 2
0
static int find_reply_socket(struct sockaddr *sa, int bc)
{

	//printf("Looking for best sock of: %s\n",sock_addr2str(sa));

	int bestsockfd = -1;
	int i;
	for (i = 0; i < socklist_len; i++) {
		struct sockaddr_storage sn;
		memset(&sn, 0, sizeof(sn));
		unsigned int snlen = sizeof(struct sockaddr_storage);

		if (getsockname(socklist[i].sockfd, (struct sockaddr *) &sn, &snlen) < 0) {
			continue;
		}

		if (sa->sa_family != sn.ss_family)
			continue;

		if (sn.ss_family == AF_INET) {
			int p1 = ntohs(((struct sockaddr_in *) sa)->sin_port);
			int p2 = ntohs(((struct sockaddr_in *) &sn)->sin_port);
			if (p1 != p2)
				continue;

		}



		if (bestsockfd == -1)
			bestsockfd = socklist[i].sockfd;

		if (!bc)
			return bestsockfd;

		struct sockaddr_storage bcaddr;

		if (!sock_getbroadcastaddr
		    ((struct sockaddr *) &sn, (struct sockaddr *) &bcaddr))
			continue;

		if (sock_cmpaddr((struct sockaddr *) &bcaddr, sa, 0))
			continue;

		bestsockfd = socklist[i].sockfd;


	}
	return bestsockfd;
}
/*!
	\brief Checks that one host (identified by the sockaddr_storage structure) belongs to an 'allowed list'.

	This function is useful after an accept() call in order to check if the connecting
	host is allowed to connect to me. To do that, we have a buffer that keeps the list of the
	allowed host; this function checks the sockaddr_storage structure of the connecting host
	against this host list, and it returns '0' is the host is included in this list.

	\param hostlist: pointer to a string that contains the list of the allowed host.

	\param sep: a string that keeps the separators used between the hosts (for example the
	space character) in the host list.

	\param from: a sockaddr_storage structure, as it is returned by the accept() call.

	\param errbuf: a pointer to an user-allocated buffer that will contain the complete
	error message. This buffer has to be at least 'errbuflen' in length.
	It can be NULL; in this case the error cannot be printed.

	\param errbuflen: length of the buffer that will contains the error. The error message cannot be
	larger than 'errbuflen - 1' because the last char is reserved for the string terminator.

	\return It returns:
	- '1' if the host list is empty
	- '0' if the host belongs to the host list (and therefore it is allowed to connect)
	- '-1' in case the host does not belong to the host list (and therefore it is not allowed to connect
	- '-2' in case or error. The error message is returned in the 'errbuf' variable.
*/
int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen)
{
    // checks if the connecting host is among the ones allowed
    if ( (hostlist) && (hostlist[0]) )
    {
        char *token;					// temp, needed to separate items into the hostlist
        struct addrinfo *addrinfo, *ai_next;
        char *temphostlist;

        temphostlist= (char *) malloc (strlen(hostlist) + 1);
        if (temphostlist == NULL)
        {
            sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen);
            return -2;
        }

        // The problem is that strtok modifies the original variable by putting '0' at the end of each token
        // So, we have to create a new temporary string in which the original content is kept
        strcpy(temphostlist, hostlist);

        token= strtok(temphostlist, sep);

        // it avoids a warning in the compilation ('addrinfo used but not initialized')
        addrinfo = NULL;

        while( token != NULL )
        {
            struct addrinfo hints;
            int retval;

            addrinfo = NULL;
            memset(&hints, 0, sizeof (struct addrinfo) );
            hints.ai_family = PF_UNSPEC;
            hints.ai_socktype= SOCK_STREAM;

            retval = getaddrinfo(token, "0", &hints, &addrinfo);
            if (retval != 0)
            {
                if (errbuf)
                {
                    snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
                    errbuf[errbuflen - 1]= 0;
                }

                SOCK_ASSERT(errbuf, 1);

                // Get next token
                token = strtok( NULL, sep);
                continue;
            }

            // ai_next is required to preserve the content of addrinfo, in order to deallocate it properly
            ai_next= addrinfo;
            while(ai_next)
            {
                if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
                {
                    free(temphostlist);
                    return 0;
                }

                // If we are here, it means that the current address does not matches
                // Let's try with the next one in the header chain
                ai_next= ai_next->ai_next;
            }

            freeaddrinfo(addrinfo);
            addrinfo= NULL;

            // Get next token
            token = strtok( NULL, sep);
        }

        if (addrinfo)
        {
            freeaddrinfo(addrinfo);
            addrinfo= NULL;
        }

        if (errbuf)
        {
            snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
            errbuf[errbuflen - 1]= 0;
        }

        free(temphostlist);
        return -1;
    }

    // No hostlist, so we have to return 'empty list'
    return 1;
}