Exemplo n.º 1
0
/*
 * \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure.
 *
 * This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks
 * to control that everything is fine (e.g. a TCP socket cannot have a mcast address, and such).
 * If an error occurs, it writes the error message into 'errbuf'.
 *
 * \param host: a pointer to a string identifying the host. It can be
 * a host name, a numeric literal address, or NULL or "" (useful
 * in case of a server socket which has to bind to all addresses).
 *
 * \param port: a pointer to a user-allocated buffer containing the network port to use.
 *
 * \param hints: an addrinfo variable (passed by reference) containing the flags needed to create the
 * addrinfo structure appropriately.
 *
 * \param addrinfo: it represents the true returning value. This is a pointer to an addrinfo variable
 * (passed by reference), which will be allocated by this function and returned back to the caller.
 * This variable will be used in the next sockets calls.
 *
 * \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 '0' if everything is fine, '-1' if some errors occurred. The error message is returned
 * in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is
 * returned into the addrinfo parameter.
 *
 * \warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when
 * it is no longer needed.
 *
 * \warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same
 * of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
 * the programmer to look at that function in order to set the 'hints' variable appropriately.
 */
int sock_initaddress(const char *host, const char *port,
    struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
{
	int retval;

	retval = getaddrinfo(host, port, hints, addrinfo);
	if (retval != 0)
	{
		/*
		 * if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
		 * error routines (errno) in UNIX; Winsock suggests using the GetLastError() instead.
		 */
		if (errbuf)
		{
#ifdef _WIN32
			sock_geterror("getaddrinfo(): ", errbuf, errbuflen);
#else
			pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
#endif
		}
		return -1;
	}
	/*
	 * \warning SOCKET: I should check all the accept() in order to bind to all addresses in case
	 * addrinfo has more han one pointers
	 */

	/*
	 * This software only supports PF_INET and PF_INET6.
	 *
	 * XXX - should we just check that at least *one* address is
	 * either PF_INET or PF_INET6, and, when using the list,
	 * ignore all addresses that are neither?  (What, no IPX
	 * support? :-))
	 */
	if (((*addrinfo)->ai_family != PF_INET) &&
	    ((*addrinfo)->ai_family != PF_INET6))
	{
		if (errbuf)
			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
		freeaddrinfo(*addrinfo);
		*addrinfo = NULL;
		return -1;
	}

	/*
	 * You can't do multicast (or broadcast) TCP.
	 */
	if (((*addrinfo)->ai_socktype == SOCK_STREAM) &&
	    (sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
	{
		if (errbuf)
			pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
		freeaddrinfo(*addrinfo);
		*addrinfo = NULL;
		return -1;
	}

	return 0;
}
/*!
	\brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' stucture.

	This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks
	to control that everything is fine (e.g. a TCP socket cannot have a mcast address, and such).
	If an error occurs, it writes the error message into 'errbuf'.

	\param address: a pointer to a user-allocated buffer containing the network address to check.
	It could be both a numeric - literal address, and it can be NULL or "" (useful in case of a server
	socket which has to bind to all addresses).

	\param port: a pointer to a user-allocated buffer containing the network port to use.

	\param hints: an addrinfo variable (passed by reference) containing the flags needed to create the
	addrinfo structure appropriately.

	\param addrinfo: it represents the true returning value. This is a pointer to an addrinfo variable
	(passed by reference), which will be allocated by this function and returned back to the caller.
	This variable will be used in the next sockets calls.

	\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 '0' if everything is fine, '-1' if some errors occurred. The error message is returned
	in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is
	returned into the addrinfo parameter.

	\warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when
	it is no longer needed.

	\warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same
	of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
	the programmer to look at that function in order to set the 'hints' variable appropriately.
*/
int sock_initaddress(const char *address, const char *port,
                     struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
{
    int retval;

    retval = getaddrinfo(address, port, hints, addrinfo);
    if (retval != 0)
    {
        // if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
        // error routines (errno) in UNIX; WIN32 suggests using the GetLastError() instead.
        if (errbuf)
#ifdef WIN32
            sock_geterror("getaddrinfo(): ", errbuf, errbuflen);
#else
            if (errbuf)
            {
                snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
                errbuf[errbuflen - 1]= 0;
            }
#endif
        return -1;
    }
    /*!
    	\warning SOCKET: I should check all the accept() in order to bind to all addresses in case
    	addrinfo has more han one pointers
    */

    // This software only supports PF_INET and PF_INET6.
    if (( (*addrinfo)->ai_family != PF_INET) && ( (*addrinfo)->ai_family != PF_INET6))
    {
        if (errbuf)
        {
            snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
            errbuf[errbuflen - 1]= 0;
        }
        return -1;
    }

    if ( ( (*addrinfo)->ai_socktype == SOCK_STREAM) && (sock_ismcastaddr( (*addrinfo)->ai_addr) == 0) )
    {
        if (errbuf)
        {
            snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
            errbuf[errbuflen - 1]= 0;
        }

        return -1;
    }

    return 0;
}